自定义 SpringBoot 启动方法的六种方式(下)

2022-03-15 23:12:50   最后更新: 2022-03-15 23:12:50   访问数量:373




 

上一篇文章中,我们介绍了六种 SpringBoot 启动时运行代码的方法,并且详细介绍了其中两个可以获取和处理 spring 启动参数的方法:

 

自定义 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.1 @Postconstruct 注解说明

 

也许你觉得编写事件响应太麻烦,那么,添加 @Postconstruct 注解的方式可能就是你想要的解决办法,这也是最常用的一种方法了。

 

只要在方法上加上这个 @Postconstruct 注解,这个方法就会在类创建完成后被立即调用。

 

3.2 使用 @Postconstruct 注解的限制

 

  1. 一个类中最多只能有一个方法添加 @Postconstruct 注解。
  2. @Postconstruct 注解修饰的方法不能具有参数和返回值,也不能是 static 方法。
  3. @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 called

postContruct method called

 

 

这种方法本质上和添加 @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.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

 

 

上述的这些方法都是可以同时添加到你的项目中,那么,这些方法一旦同时添加,到底他们之间执行的先后顺序如何呢?

 

他们是按照下面的顺序来执行的:

 

  • Constructor
  • PostContruct method
  • afterPropertiesSet method
  • Bean init Method
  • ApplicationStartedEvent
  • ApplicationRunner Or CommandLineRunner
  • ApplicationReadyEvent

 

至于 ApplicationRunner 与 CommandLineRunner 的实现类,我们可以通过 @Order 注解决定他们之间的优先级。

 

 

https://stacktraceguru.com/springboot/run-method-on-startup#application-runner

 

 

欢迎关注微信公众号,以技术为主,涉及历史、人文等多领域的学习与感悟,每周三到七篇推文,只有全部原创,只有干货没有鸡汤

 

Spring 从入门到实战






java      技术贴      springboot      boot     


京ICP备2021035038号