Original difficult, if reproduced, please indicate the source https://www.cnblogs.com/baixianlong/p/11117665.html , thanks to support Ha! ! !
First, the problem
In the usual course of business module development, we will inevitably need to do some global tasks, cache, threads, etc. initialization work, then how to solve this problem? There are a number of ways, but the specific but also how to choose?
Second, the resource initialization
1, since the initialization of resources do, then you need to know about springboot boot process (generally speaking here at the boot process, detail: https://www.cnblogs.com/dennyzhangdd/p/8028950.html )
According to the foregoing analysis, Spring-boot to start the process container can be divided generally into two parts:
- Performing annotation: bean scan the specified range, the automatic loading configuration class corresponding to loads bean IOC container.
- The method particularly man SpringAppliocation.run (), through the whole process SpringApplicationEvent (classic spring event-driven model), there are six sub-classes:
- ApplicationFailedEvent.class
- ApplicationPreparedEvent.class
- ApplicationReadyEvent.class
- ApplicationStartedEvent.class
- ApplicationStartingEvent.class
- SpringApplicationEvent.class
2、CommandLineRunner和ApplicationRunner
由上可知,我们只要实现这两个中的任何一个接口便可以完成我们的资源初始化任务,可以看到它们的加载是在容器完全启动之前。它两的区别是:前者的run方法参数是String...args,直接传入字符串,后者的参数是ApplicationArguments,对参数进行了封装。功能上是一样的。同时也可以使用 @Order注解来实现资源加载的先后顺序,值越小,优先级越高。实例如下:
@Component
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("...init resources by implements CommandLineRunner");
}
}
@Component
@Order(2)
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
System.out.println("...init resources by implements ApplicationRunner");
}
}
3、@PostConstruct
在具体Bean的实例化过程中执行,@PostConstruct注解的方法,会在构造方法之后执行,顺序为Constructor > @Autowired > @PostConstruct > 静态方法,所以这个注解就避免了一些需要在构造方法里使用依赖组件的尴尬(与之对应的还有@PreDestroy,在对象消亡之前执行,原理差不多)。使用特点如下:
- 只有一个非静态方法能使用此注解
- 被注解的方法不得有任何参数
- 被注解的方法返回值必须为void
- 被注解方法不得抛出已检查异常
此方法只会被执行一次
@Component public Class AAA { @Autowired private BBB b; public AAA() { System.out.println("此时b还未被注入: b = " + b); } @PostConstruct private void init() { System.out.println("此时b已经被注入: b = " + b); } }
4、InitializingBean
InitializingBean 是 Spring 提供的一个接口,只包含一个方法 afterPropertiesSet()。凡是实现了该接口的类,当其对应的 Bean 交由 Spring 管理后,当其必要的属性全部设置完成后,Spring 会调用该 Bean 的 afterPropertiesSet()。在Bean在实例化的过程中执执行顺序为:Constructor > @PostConstruct > InitializingBean > init-method
public class InitSequenceBean implements InitializingBean {
public InitSequenceBean() {
System.out.println("InitSequenceBean: constructor");
}
@PostConstruct
public void postConstruct() {
System.out.println("InitSequenceBean: postConstruct");
}
public void initMethod() {
System.out.println("InitSequenceBean: init-method");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitSequenceBean: afterPropertiesSet");
}
}
5、ApplicationListener
ApplicationListener is spring listener, it can be used to monitor events, the typical observer mode. If there is a ApplicationListener Bean container whenever ApplicationContext release ApplicationEvent, ApplicationListener Bean will automatically be triggered. This event mechanism must require the program to display the trigger. There are some built-in which the spring event, upon completion of certain operations will be issued some event action. For example, listen ContextRefreshedEvent event, when all of the bean are initialized and after a successful completion of loading will trigger the event, to achieve ApplicationListener
@Component
public class DataSourceInitListener implements ApplicationListener<ContextRefreshedEvent> {//ContextRefreshedEvent为启动事件
private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceInitListener.class);
@Autowired
private SystemConfigService systemConfigService;
@Autowired
private ItemService itemService;
@Autowired
private SystemResultService systemResultService;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if(event.getApplicationContext().getParent() == null) {//判断是否执行过,执行过则不再执行
LOGGER.info("初始化systemConfig数据");
systemConfigService.initConfig();
LOGGER.info("初始化返回消息数据");
systemResultService.initResult();
LOGGER.info("系统初始化结束...........");
}
}
}
Third, the summary
- Some of this resource initialization method say almost, which inevitably some the wrong place, or biased understanding of where we are welcome to put forward!
Personal blog address:
cnblogs: https://www.cnblogs.com/baixianlong
segmentfault:https://segmentfault.com/u/baixianlong