69.原理解析-自定义事件监听组件
自定义事件监听组件
在上面了解了在程序启动时准备工作和启动过程会扫描 spring.factories 中的配置,拿到要启动的各种配置。这也说明可以自己自定义一些程序启动时会自动扫描的文件,然后在 resources\META-INF\ 下创建 spring.factories 文件,里面把自定义的文件加进去好让扫描到,加入容器中,在启动过程中被调用,做一些准备工作。
自定义 ApplicationContextInitializer
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
System.out.println("MyApplicationContextInitializer....initialize");
}
}
自定义 ApplicationListener
public class MyApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
System.out.println("MyApplicationListener....onApplicationEvent");
}
}
自定义 SpringApplicationRunListener
这个 SpringApplicationRunListener 接口里面的方法都是默认实现的,可以全部实现,拿来做一些准备。
而且,实现类需要一个有参构造器,参数类型一个是 SpringApplication ,一个 String 。否则就报错提示少一个参数为 xxx 的构造方法
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
private SpringApplication application;
public MySpringApplicationRunListener(SpringApplication application,String[] args){
this.application=application;
}
@Override
public void starting() {
System.out.println("MySpringApplicationRunListener...starting");
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
System.out.println("MySpringApplicationRunListener...environmentPrepared");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener...contextPrepared");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener...contextLoaded");
}
@Override
public void started(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener...started");
}
@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener...running");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("MySpringApplicationRunListener...failed");
}
}
底下这两个类型的组件能通过 @Order 进行排序录入数组,然后根据优先级遍历调用 run 方法。属性数字越大优先级越高
自定义 CommandLineRunner
@Component
@Order(2)
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner...run");
}
}
自定义 ApplicationRunner
@Component
@Order(1)
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("MyApplicationRunner...run");
}
}
在 spring.factories 中
这个内容可以参照官方依赖,直接复制,然后在后面添加上自定义的配置类全路径【copy reference】
#
Initializers
org.springframework.context.ApplicationContextInitializer=\
com.xl.bibiji.custom.MyApplicationContextInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
com.xl.bibiji.custom.MyApplicationListener
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
com.xl.bibiji.custom.MySpringApplicationRunListener
启动后
在上面观察过源码,了解过各种配置的获取加载调用方法时间,就能根据这个顺序对程序启动时实现对应的接口在相应的方法里面加一些初始化配置。
MyApplicationListener....onApplicationEvent //自定义 ApplicationListener
MySpringApplicationRunListener...starting //自定义 SpringApplicationRunListener
MyApplicationListener....onApplicationEvent
MySpringApplicationRunListener...environmentPrepared
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.7.RELEASE)
MyApplicationContextInitializer....initialize //自定义 ApplicationContextInitializer
MyApplicationListener....onApplicationEvent
MySpringApplicationRunListener...contextPrepared
2022-03-07 20:35:10.978 INFO 21684 --- [ main] com.xl.bibiji.BibijiApplication : Starting BibijiApplication on xyk with PID 21684 (D:\IDEAProject\bibiji\target\classes started by xyk in D:\IDEAProject\bibiji)
2022-03-07 20:35:10.981 INFO 21684 --- [ main] com.xl.bibiji.BibijiApplication : No active profile set, falling back to default profiles: default
MyApplicationListener....onApplicationEvent
MySpringApplicationRunListener...contextLoaded
2022-03-07 20:35:12.141 INFO 21684 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-03-07 20:35:12.153 INFO 21684 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-03-07 20:35:12.154 INFO 21684 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.41]
2022-03-07 20:35:12.295 INFO 21684 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-03-07 20:35:12.295 INFO 21684 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1244 ms
2022-03-07 20:35:12.512 INFO 21684 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2022-03-07 20:35:12.711 INFO 21684 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
MyApplicationListener....onApplicationEvent
MyApplicationListener....onApplicationEvent
2022-03-07 20:35:12.724 INFO 21684 --- [ main] com.xl.bibiji.BibijiApplication : Started BibijiApplication in 2.227 seconds (JVM running for 3.239)
MyApplicationListener....onApplicationEvent
MyApplicationListener....onApplicationEvent
MySpringApplicationRunListener...started
MyApplicationRunner...run //自定义 ApplicationRunner
MyCommandLineRunner...run //自定义 CommandLineRunner
MyApplicationListener....onApplicationEvent
MyApplicationListener....onApplicationEvent
MySpringApplicationRunListener...running