• Spring Boot中的类初始化方法的执行先后顺序


    各种类初始化方法的执行先后顺序

    已验证这六种方法初始化的先后顺序如下:

    SpringApplication > ServletContextListener > InitializingBean > PostConstruct > ApplicationRunner > CommandLineRunner

    main方法

    @SpringBootApplication
    public class DemoApplication {
    
        public static void main(String[] args) {
            System.out.println("****************** DemoApplication.run before ******************");
            SpringApplication.run(DemoApplication.class, args);
            System.out.println("****************** DemoApplication.run after ******************");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    实现ServletContextListener接口

    ServletContextListener接口用于服务启动时自动加载函数,需加载的类必须实现ServletContextListener接口,且重写该接口中的两个方法。

    public interface ServletContextListener extends EventListener {
    	// 服务器起动时加载内容
        default void contextInitialized(ServletContextEvent sce) {
        }
    		
    	// 服务器关闭时加载的内容
        default void contextDestroyed(ServletContextEvent sce) {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    @Component
    public class TestServletContextListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            System.out.println("****************** TestServletContextListener.contextInitialized() ******************");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            System.out.println("****************** contextInitialized.contextDestroyed() ******************");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    实现InitializingBean接口

    InitializingBean接口为bean提供了属性初始化后的处理方法,只拥有一个afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。

    public interface InitializingBean {
        void afterPropertiesSet() throws Exception;
    }
    
    • 1
    • 2
    • 3
    @Component
    public class TestInitializingBean implements InitializingBean {
    
        @Override
        public void afterPropertiesSet() {
            System.out.println("****************** TestInitializingBean.afterPropertiesSet() ******************");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    @PostConstruct注解

    @PostConstruct注解是Java Jdk提供的注解,Java EE5引入了@PostConstruct@PreDestroy两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作。

    @Component
    public class TestPostConstruct {
         
    	@PostConstruct
        public void init(){
            System.out.println("****************** TestPostConstruct.init() ******************");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    实现ApplicationRunner

    ApplicationRunner、CommandLineRunner常用于服务启动的时候执行一些任务,如读取配置文件,Redis数据预热等操作。

    ApplicationRunner的run方法的参数为ApplicationArguments,是对main方法的args原始参数做了进一步的封装。

    @Component
    public class TestApplicationRunner implements ApplicationRunner {
         
    	@Override
    	public void run(ApplicationArguments args) {
    		System.out.println("****************** TestApplicationRunner.run() ******************");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    实现CommandLineRunner

    ApplicationRunner、CommandLineRunner常用于服务启动的时候执行一些任务,如读取配置文件,Redis数据预热等操作。

    CommandLineRunner接口中run方法的参数为String数组。多个CommandLineRunner可以被同时执行在同一个spring上下文中并且执行顺序是以order注解的参数顺序一致。

    @Component
    public class TestCommandLineRunner implements CommandLineRunner {
    
    	@Override
    	public void run(String... args) {
    		System.out.println("****************** TestCommandLineRunner.run() ******************");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    执行结果

    执行结果如下:

    ****************** DemoApplication.run before ******************
    ****************** DemoApplication.run before ******************
    ****************** TestServletContextListener.contextInitialized() ******************
    ****************** TestInitializingBean.afterPropertiesSet() ******************
    ****************** TestPostConstruct.init() ******************
    ****************** TestApplicationRunner.run() ******************
    ****************** TestCommandLineRunner.run() ******************
    ****************** DemoApplication.run after ******************
    ****************** contextInitialized.contextDestroyed() ******************
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意:DemoApplication.run before执行2次是因为pom文件引入了热部署的Jar包引起的,将其删除或者注释即可解决打印两次的问题。

    	<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <optional>true</optional>
            </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    计算机体系结构:不同方案的机器性能比较例题(1.6)
    二维码智慧门牌管理系统升级解决方案:运营可视化之道
    【算法3.7】spfa(完结)
    JavaScript之DOM常用属性及方法详解
    照片怎么压缩变小?
    目标检测YOLO算法,先从yolov1开始
    VS Code 在线运行:code-server部署(系列一)
    五、stm32-SysTick(系统定时器)
    我开始使用了Typescript
    链表反转-LeetCode206
  • 原文地址:https://blog.csdn.net/qq_38628046/article/details/126178298