添加 SpringBoot 自定义启动代码的六种方式(下)
1. 引言
上一篇文章中,我们介绍了六种 SpringBoot 启动时运行代码的方法,并且详细介绍了其中两个可以获取和处理 spring 启动参数的方法:
添加 SpringBoot 自定义启动代码的六种方式(上)
本文我们继续来介绍剩下的四种方式。
2. SpringBoot 启动事件与监听
2.1 SpringBoot 的启动事件
在 org.springframework.boot.context.event 包中,定义了 SpringBoot 的启动事件类:
-
ApplicationStartingEvent — ApplicationContext 创建完成后触发。
-
ApplicationContextInitializedEvent — Spring 项目启动时,已经完成 ApplicationContext 创建且调用所有的 ApplicationContextInitializers 接口的实现类后触发,但此时 bean 还尚未加载。
-
ApplicationPreparedEvent — bean 全部创建完成后触发,但此时 ApplicationContext 还没有更新。
-
ApplicationStartedEvent — ApplicationContext 完成更新后触发,但此时 ApplicationRunner 与 CommandLineRunner 接口的实现类还尚未被调用。
-
ApplicationReadyEvent — 完成调用 ApplicationRunner 与 CommandLineRunner 接口的所有实现类后触发。
-
ApplicationFailedEvent — 启动失败后触发。
有了上述启动的六个关键时刻触发的事件,我们就可以编写事件响应程序来实现自定义处理了。
可以看到,相较于上一篇文章中介绍的 ApplicationRunner 与 CommandLineRunner 接口,监听和响应启动事件让我们对项目的 启动有了更细粒度的控制。
除了上一篇文章中已经提到的 ApplicationRunner 与 CommandLineRunner 接口,上面还提到了 ApplicationContext、ApplicationContextInitializers 接口等,这些关键概念我们后续会有文章专门介绍,敬请期待下文。
2.2 编写事件响应代码
通过向注解 @EventListener 传入我们想要监听的事件类,就可以实现对这一事件的响应,例如:
@Component
public class RunAfterStartup{
@EventListener(ApplicationReadyEvent.class)
public void runAfterStartup() {
System.out.println("Yaaah, I am running........");
}
显然,我们不能像上一篇文章中那样轻松地获取启动参数了。
启动 SpringBoot,我们看到上述代码打印出了:
Yaaah, I am running……..
3. 添加 @Postconstruct 注解
3.1 @Postconstruct 注解说明
也许你觉得编写事件响应太麻烦,那么,添加 @Postconstruct 注解的方式可能就是你想要的解决办法,这也是最常用的一种方法了。
只要在方法上加上这个 @Postconstruct 注解,这个方法就会在类创建完成后被立即调用。
3.2 使用 @Postconstruct 注解的限制
-
一个类中最多只能有一个方法添加 @Postconstruct 注解。
-
@Postconstruct 注解修饰的方法不能具有参数和返回值,也不能是 static 方法。
-
@Postconstruct 注解是 javaEE 的功能,而并非 Spring 的功能,因此,自 java11 不再默认包含 javaEE 开始,如果你想要使用这一功能,你需要手动添加 java.ee.ee 包到项目中。
3.2 示例
@Component
public class PostContructImpl {
public PostContructImpl() {
System.out.println("PostContructImpl Constructor called");
}
@PostConstruct
public void runAfterObjectCreated() {
System.out.println("PostContruct method called");
}
}
执行上述代码,打印出了:
PostContructImpl Constructor calledpostContruct method called
4. 实现 InitializingBean 接口
这种方法本质上和添加 @Postconstruct 注解是一样的。都会在这个类完成创建和初始化工作后调用。
我们只要实现 InitializingBean 的 afterPropertiesSet 方法即可。
例如:
@Component
public class InitializingBeanImpl implements InitializingBean {
public InitializingBeanImpl() {
System.out.println("InitializingBeanImpl Constructor called");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBeanImpl afterPropertiesSet method called");
}
}
5. 通过 Bean 的 initMethod
5.1 简介
Spring 的 Bean 拥有一个属性 initMethod 可以让我们指定 bean 创建时的初始化方法,借助这个属性,我们就可以在其中添加我们想要的启动代码了。
5.2 注意事项
需要注意的是,这个 initMethod 必须是没有参数和返回值。但这个方法可以使 static 的甚至是 private 的。
5.3 示例
例如:
public class BeanInitMethodImpl {
public void runAfterObjectCreated() {
System.out.println("yooooooooo......... someone called me");
}
}
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean(initMethod="runAfterObjectCreated")
public BeanInitMethodImpl getFunnyBean() {
return new BeanInitMethodImpl();
}
}
打印出了:
yooooooooo……… someone called me
6. 六种方法的执行顺序
上述的这些方法都是可以同时添加到你的项目中,那么,这些方法一旦同时添加,到底他们之间执行的先后顺序如何呢?
他们是按照下面的顺序来执行的:
-
Constructor
-
PostContruct method
-
afterPropertiesSet method
-
Bean init Method
-
ApplicationStartedEvent
-
ApplicationRunner Or CommandLineRunner
-
ApplicationReadyEvent
至于 ApplicationRunner 与 CommandLineRunner 的实现类,我们可以通过 @Order 注解决定他们之间的优先级。
附录 — 参考资料
https://stacktraceguru.com/springboot/run-method-on-startup
《添加 SpringBoot 自定义启动代码的六种方式(下)》来自互联网,仅为收藏学习,如侵权请联系删除。本文URL:https://www.bookhoes.com/4874.html