1. 实现ServletContextListener接口
@Component
public class SpringBootInitialization1 implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("方式一:实现ServletContextListener接口");
}
}
2. 实现ApplicationListener接口
@Component
public class SpringBootInitialization2 implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("方式四:实现ApplicationListener<ContextRefreshedEvent>接口");
}
}
3. 实现ServletContextAware接口
@Component
public class SpringBootInitialization3 implements ServletContextAware {
@Override
public void setServletContext(ServletContext servletContext) {
System.out.println("方式三:实现ServletContextAware接口");
}
}
4. 方法上加注解@PostConstruct
@Component
public class SpringBootInitialization4 {
@PostConstruct
public static void init() {
System.out.println("方式二:方法上加注解@PostConstruct");
}
}
5. 实现ApplicationRunner接口
@Component
public class SpringBootInitialization5 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("方式五:实现ApplicationRunner接口");
}
}
6. 实现CommandLineRunner接口
@Component
public class SpringBootInitialization6 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("方式六:实现CommandLineRunner接口");
}
}
7. 实现InitializingBean接口
@Component
public class SpringBootInitialization7 implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("方式七:实现InitializingBean接口");
}
}
以上加载方法的顺序
package com.ipebg.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ServletContextAware;
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* 2021/3/9 上午 11:02
*/
@Slf4j
@Component
public class TestInit implements InitializingBean, CommandLineRunner, ApplicationRunner,
ApplicationListener<ContextRefreshedEvent>, ServletContextAware, ServletContextListener {
public TestInit() {
log.error("++ TestInit construct... ++");
}
@Override
public void afterPropertiesSet() throws Exception {
log.error("++ InitializingBean afterPropertiesSet... ++");
}
/**
* Callback used to run the bean.
*
* @param args incoming application arguments
* @throws Exception on error
*/
@Override
public void run(ApplicationArguments args) throws Exception {
log.error("++ ApplicationRunner run... ++");
}
/**
* Callback used to run the bean.
*
* @param args incoming main method arguments
* @throws Exception on error
*/
@Override
public void run(String... args) throws Exception {
log.error("++ CommandLineRunner run... ++");
}
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
log.error("++ ApplicationListener<ContextRefreshedEvent> onApplicationEvent... ++");
}
@Override
public void setServletContext(ServletContext servletContext) {
log.error("++ ServletContextAware setServletContext... ++");
}
@Override
public void contextInitialized(ServletContextEvent sce) {
log.error("++ ServletContextListener contextInitialized... ++");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.error("++ ServletContextListener contextDestroyed... ++");
}
@PostConstruct
public void init(){
log.error("++ PostConstruct init... ++");
}
}
...
Tomcat initialized with port(s): 8082 (http)
++ TestInit construct... ++
++ ServletContextAware setServletContext... ++
++ PostConstruct init... ++
++ InitializingBean afterPropertiesSet... ++
++ ServletContextListener contextInitialized... ++
...
++ ApplicationListener<ContextRefreshedEvent> onApplicationEvent... ++
Tomcat started on port(s): 8082 (http) with context path ''
++ ApplicationRunner run... ++
++ CommandLineRunner run... ++
Bean初始化-依赖注入(如果有依赖其他Bean)-ServletContextAware-@PostConstruct-InitializingBean接口
ServletContextListener-ApplicationListener<ContextRefreshedEvent>-ApplicationRunner接口-CommandLineRunner接口
@PostConstruct 服务初始化过程中,执行该方法,该方法不结束无法提供服务
实现CommandLineRunner接口 服务初始化之后,执行方法
@order
如果项目中既有实现了 ApplicationRunner 接口的初始化类,又有实现了 CommandLineRunner 接口的初始化类,那么会是哪一个先执行呢?测试告诉我们,答案是实现了 ApplicationRunner 接口的初始化类先执行,我想这点倒是不需要大家过分去关注为什么。但如果需要改变两个初始化类之间的默认执行顺序,那么使用 @Order 注解就可以帮助我们解决这个问题。
@Component
@Order(1)//order的值越小,该初始化类也就越早执行。
public class MyCommandLineRunner implements CommandLineRunner {
...
}
ApplicationRunner和CommandLineRunner
摘自SpringBoot官方文档:
Tasks expected to run during startup should be executed by CommandLineRunner and ApplicationRunner components instead of using Spring component lifecycle callbacks such as @PostConstruct.
期望在启动期间运行的任务应该由CommandLineRunner和ApplicationRunner组件执行,而不是使用Spring组件生命周期回调,如@PostConstruct。
如果希望在SpringApplication启动后运行一些特定的代码,可以实现ApplicationRunner或CommandLineRunner接口。这两个接口以相同的方式工作,并提供一个run方法,在SpringApplication.run()
完成之前调用该方法。
ApplicationRunner的run方法接收一个ApplicationArguments参数,而CommandLineRunner的run方法可以接收一个字符串的数组。
如果想要指定他们的顺序,可以有如下选择:
- 额外指定实现
org.springframework.core.Ordered
接口。 - 使用
org.springframework.core.annotation.Order
注解。