引言
在项目开发的过程中,有时候需要在项目启动时执行特定方法,比如初始化临时数据库,提前把数据放到缓存里,检查运行环境等等。
👀 运行参数 -a -b -c --name=zunmx
解决方案
静态方法
ℹ:不足之处是不能通过容器进行注入其它方法,可用性比较低,应用有场景,但是并不多。
@Component()
public class AutoRun {
@Autowired
private InsideDBO insideDBO;
static {
System.out.println("自动运行方法:静态方法");
System.out.println(" 不能通过容器注入方法。"); // 这里是不能使用insideDBO的
}
}
通过PostConstruct注解
@Component
public class AutoRun2 {
@Autowired
private InsideDBO insideDBO;
@PostConstruct
public void run() {
System.out.println("自动运行方法:PostConstruct");
insideDBO.hello();
}
}
通过实现ServletContextAware接口
ℹ:这个只限于servlet工程。web应用被加载之后,服务器会创建出代表整个web应用的ServletContext对象,跟随于servlet的生命周期。
@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启动完成后指定的调用
@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);
}
}
}
执行顺序
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: 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在组件扫描的时候,也是根据类名进行排序,名字在前的先被托管,名字在后的后被托管,结果如下所示
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: 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,给他们都加上下面的代码
public void hello() {
System.out.println(" hello2 或者 3 或者 4");
}
执行结果
[#] 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
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
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
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
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
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");
}
}

评论 0
还没有评论,来说点什么吧。