背景
这周遇到一件很棘手的事情。
在启动某个 service 时,我需要初始化一个缓存。按照之前的逻辑,初始化只需要从本地存储中加载一个文件就行了,当时用 Spring 的 @PostConstruct 注解成功解决了这个问题:
@Service
public class MyService {
@Resource
SomeDao someDao;
@PostConstruct
private void init() {
}
}
但后来的需求变了,初始化的时候不仅需要从本地存储加载文件,而且需要请求一个数据库,拿到相关数据!
这个时候就遇到一个问题:在初始化 MyService 时,其他组件(或者 class)不一定已经完成了初始化。能不能顺利执行,取决于随机的初始化顺序。
果然,我在启动应用时,有时候能顺利启动,有时候就会报错,就是某个组件(或者某个 classs)不可用。
后来试了 InitializingBean 的 afterPropertiesSet 方法,但也不行。因为 afterPropertiesSet 执行的时候只是保证了该组件下的 property 都已经准备好了,比如在上面的例子中,MyService 的 someDao 准备好了。
但真正执行 someDao 的某个方法的时候,可能又会用到一些其他组件或者 Class,而这些组件或者 Class 可能还没有准备好!
果然,我试了之后,还是有的时候可以,有的时候就会提示某个 class not found !
Spring Boot 启动之后执行代码逻辑
最后终于找到了解决方法:
@Service
public class MyService {
@Resource
SomeDao someDao;
@EventListener(ApplicationReadyEvent.class)
public void someMethod() {
}
}
简单来说,使用 @EventListener(ApplicationReadyEvent.class) 能够保证,该方法会在 Spring Boot 启动之后马上触发,而且所有组件和 class 一定都已经是可用状态了!解决了我遇到的问题。
参考链接
Running code after Spring Boot starts
|