Loading... # 引言 在项目开发的过程中,有时候需要在项目启动时执行特定方法,比如初始化临时数据库,提前把数据放到缓存里,检查运行环境等等。 👀 运行参数 `-a -b -c --name=zunmx` # 解决方案 ## 静态方法 ℹ:不足之处是不能通过容器进行注入其它方法,可用性比较低,应用有场景,但是并不多。 ```java @Component() public class AutoRun { @Autowired private InsideDBO insideDBO; static { System.out.println("自动运行方法:静态方法"); System.out.println(" 不能通过容器注入方法。"); // 这里是不能使用insideDBO的 } } ``` ## 通过`PostConstruct`注解 ```java @Component public class AutoRun2 { @Autowired private InsideDBO insideDBO; @PostConstruct public void run() { System.out.println("自动运行方法:PostConstruct"); insideDBO.hello(); } } ``` ## 通过实现`ServletContextAware`接口 ℹ:这个只限于servlet工程。web应用被加载之后,服务器会创建出代表整个web应用的ServletContext对象,跟随于servlet的生命周期。 ```java @Component public class AutoRun3 implements ServletContextAware { @Autowired private InsideDBO insideDBO; public AutoRun3(){ System.out.println("A3类被实例化了"); } @Override public void setServletContext(ServletContext servletContext) { System.out.println("自动运行方法:实现ServletContextAware接口"); insideDBO.hello(); } } ``` ## 实现`ApplicationRunner`接口 ℹ:此方法在Springboot启动完成后指定的调用 ```java @Component public class AutoRun4 implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("启动时自动执行 ApplicationRunner 的 run 方法"); Set<String> optionNames = args.getOptionNames(); for (String optionName : optionNames) { System.out.printf("这是传过来的参数[%s],参数值为%s \n", optionName, args.getOptionValues(optionName)); } String[] sourceArgs = args.getSourceArgs(); for (String sourceArg : sourceArgs) { System.out.printf("这是传过来sourceArgs[%s] \n", sourceArg); } } } ``` # 执行顺序 ```bash . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.14) 2023-08-04 10:47:11.125 INFO 5044 --- [ restartedMain] t.zunmx.dbmanager.DbManagerApplication : Starting DbManagerApplication using Java 1.8.0_151 on ZUNMX with PID 5044 (E:\StudyCode\Java\DBManager\target\classes started by 36083 in E:\StudyCode\Java\DBManager) 2023-08-04 10:47:11.125 INFO 5044 --- [ restartedMain] t.zunmx.dbmanager.DbManagerApplication : No active profile set, falling back to 1 default profile: "default" 2023-08-04 10:47:11.151 INFO 5044 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable 2023-08-04 10:47:11.151 INFO 5044 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' 2023-08-04 10:47:11.629 INFO 5044 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2023-08-04 10:47:11.633 INFO 5044 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2023-08-04 10:47:11.633 INFO 5044 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.78] 2023-08-04 10:47:11.670 INFO 5044 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2023-08-04 10:47:11.670 INFO 5044 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 519 ms 自动运行方法:静态方法 不能通过容器注入方法。 A1类被实例化了 A2类被实例化了 自动运行方法:PostConstruct 这是组件中的方法:hello A3类被实例化了 自动运行方法:实现ServletContextAware接口 这是组件中的方法:hello 2023-08-04 10:47:11.830 INFO 5044 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2023-08-04 10:47:11.847 INFO 5044 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2023-08-04 10:47:11.853 INFO 5044 --- [ restartedMain] t.zunmx.dbmanager.DbManagerApplication : Started DbManagerApplication in 0.907 seconds (JVM running for 1.587) 启动时自动执行 ApplicationRunner 的 run 方法 这是组件中的方法:hello 这是传过来的参数[name],参数值为[zunmx] 这是传过来sourceArgs[-a] 这是传过来sourceArgs[-b] 这是传过来sourceArgs[-c] 这是传过来sourceArgs[--name=zunmx] ``` 如果改变了方法的名称,也就是说,springboot在组件扫描的时候,也是根据类名进行排序,名字在前的先被托管,名字在后的后被托管,结果如下所示 ```bash . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.14) 2023-08-04 10:48:19.079 INFO 21316 --- [ restartedMain] t.zunmx.dbmanager.DbManagerApplication : Starting DbManagerApplication using Java 1.8.0_151 on ZUNMX with PID 21316 (E:\StudyCode\Java\DBManager\target\classes started by 36083 in E:\StudyCode\Java\DBManager) 2023-08-04 10:48:19.080 INFO 21316 --- [ restartedMain] t.zunmx.dbmanager.DbManagerApplication : No active profile set, falling back to 1 default profile: "default" 2023-08-04 10:48:19.107 INFO 21316 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable 2023-08-04 10:48:19.107 INFO 21316 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' 2023-08-04 10:48:19.670 INFO 21316 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2023-08-04 10:48:19.675 INFO 21316 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2023-08-04 10:48:19.675 INFO 21316 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.78] 2023-08-04 10:48:19.716 INFO 21316 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2023-08-04 10:48:19.716 INFO 21316 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 609 ms A3类被实例化了 自动运行方法:实现ServletContextAware接口 这是组件中的方法:hello A2类被实例化了 自动运行方法:PostConstruct 这是组件中的方法:hello 自动运行方法:静态方法 不能通过容器注入方法。 A1类被实例化了 2023-08-04 10:48:19.885 INFO 21316 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2023-08-04 10:48:19.903 INFO 21316 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2023-08-04 10:48:19.910 INFO 21316 --- [ restartedMain] t.zunmx.dbmanager.DbManagerApplication : Started DbManagerApplication in 1.02 seconds (JVM running for 1.836) 启动时自动执行 ApplicationRunner 的 run 方法 这是组件中的方法:hello 这是传过来的参数[name],参数值为[zunmx] 这是传过来sourceArgs[-a] 这是传过来sourceArgs[-b] 这是传过来sourceArgs[-c] 这是传过来sourceArgs[--name=zunmx] ``` ## 貌似顺序和文件名有关 那么如果他们之间有依赖关系,那么spring会如何处理呢? 我们稍微改一下AutoRun2 3 4,给他们都加上下面的代码 ```java public void hello() { System.out.println(" hello2 或者 3 或者 4"); } ``` 执行结果 ```bash [#] initialize starting 11:02:08.604 [Thread-1] DEBUG org.springframework.boot.devtools.restart.classloader.RestartClassLoader - Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@45c59d95 [#] initialize starting . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.14) 2023-08-04 11:02:08.801 INFO 30172 --- [ restartedMain] t.zunmx.dbmanager.DbManagerApplication : Starting DbManagerApplication using Java 1.8.0_151 on ZUNMX with PID 30172 (E:\StudyCode\Java\DBManager\target\classes started by 36083 in E:\StudyCode\Java\DBManager) 2023-08-04 11:02:08.802 INFO 30172 --- [ restartedMain] t.zunmx.dbmanager.DbManagerApplication : No active profile set, falling back to 1 default profile: "default" 2023-08-04 11:02:08.827 INFO 30172 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable 2023-08-04 11:02:08.827 INFO 30172 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' 2023-08-04 11:02:09.325 INFO 30172 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2023-08-04 11:02:09.330 INFO 30172 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2023-08-04 11:02:09.330 INFO 30172 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.78] 2023-08-04 11:02:09.367 INFO 30172 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2023-08-04 11:02:09.367 INFO 30172 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 540 ms A1自动运行方法:静态方法 A1 不能通过容器注入方法。 A1类被实例化了 A2类被实例化了 A3类被实例化了 A4类被实例化了 A3自动运行方法:实现ServletContextAware接口 这是组件中的方法:hello hello4 A2自动运行方法:PostConstruct 这是组件中的方法:hello hello3 2023-08-04 11:02:09.545 INFO 30172 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2023-08-04 11:02:09.565 INFO 30172 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2023-08-04 11:02:09.571 INFO 30172 --- [ restartedMain] t.zunmx.dbmanager.DbManagerApplication : Started DbManagerApplication in 0.962 seconds (JVM running for 1.664) A4启动时自动执行 ApplicationRunner 的 run 方法 这是组件中的方法:hello A4这是传过来的参数[name],参数值为[zunmx] A4这是传过来sourceArgs[-a] A4这是传过来sourceArgs[-b] A4这是传过来sourceArgs[-c] A4这是传过来sourceArgs[--name=zunmx] [#] initialize done ``` # 完整代码实例 ## AutoRun.java ```java package top.zunmx.dbmanager.utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component() public class AutoRun { @Autowired private InsideDBO insideDBO; public AutoRun(){ System.out.println("A1类被实例化了"); } static { System.out.println("A1自动运行方法:静态方法"); System.out.println("A1 不能通过容器注入方法。"); } public void hello(){ System.out.println(" hello1"); } } ``` ## AutoRun2.java ```java package top.zunmx.dbmanager.utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component() public class AutoRun { @Autowired private InsideDBO insideDBO; public AutoRun(){ System.out.println("A1类被实例化了"); } static { System.out.println("A1自动运行方法:静态方法"); System.out.println("A1 不能通过容器注入方法。"); } public void hello(){ System.out.println(" hello1"); } } ``` ## AutoRun3.java ```java package top.zunmx.dbmanager.utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.context.ServletContextAware; import javax.servlet.ServletContext; @Component public class AutoRun3 implements ServletContextAware { @Autowired private InsideDBO insideDBO; @Autowired private AutoRun4 autoRun4; public AutoRun3(){ System.out.println("A3类被实例化了"); } @Override public void setServletContext(ServletContext servletContext) { System.out.println("A3自动运行方法:实现ServletContextAware接口"); insideDBO.hello(); autoRun4.hello(); } public void hello(){ System.out.println(" hello3"); } } ``` ## AutoRun4.java ```java package top.zunmx.dbmanager.utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import java.util.Set; @Component public class AutoRun4 implements ApplicationRunner { @Autowired private InsideDBO insideDBO; public AutoRun4(){ System.out.println("A4类被实例化了"); } @Override public void run(ApplicationArguments args) throws Exception { System.out.println("A4启动时自动执行 ApplicationRunner 的 run 方法"); insideDBO.hello(); Set<String> optionNames = args.getOptionNames(); for (String optionName : optionNames) { System.out.printf("A4这是传过来的参数[%s],参数值为%s \n", optionName, args.getOptionValues(optionName)); } String[] sourceArgs = args.getSourceArgs(); for (String sourceArg : sourceArgs) { System.out.printf("A4这是传过来sourceArgs[%s] \n", sourceArg); } } public void hello(){ System.out.println(" hello4"); } } ``` ## InsideDBO.java ```java package top.zunmx.dbmanager.utils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @Component @Scope("singleton") public class InsideDBO { public void hello() { System.out.println(" 这是组件中的方法:hello"); } } ``` © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏