• 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
  • 相关阅读:
    安装KB5039212更新卡在25% 或者 96% 进度
    3D目标检测实战 | 图解KITTI数据集与数据格式
    三姐妹不吸烟患肺癌,做饭人需要了解油烟的三大危害
    Docker13:容器互联----link (给新手玩的,进阶方法是 自定义网络)
    Win11打不开exe应用程序怎么办?Win11无法打开exe程序解决方法
    275-I/O阻塞和非阻塞,同步和异步
    一套基于 SpringBoot 和 Vue 的企业级中后台 java 开源项目
    设定并理解随机数种子 && Pytorch在Dataloader类中设置shuffle的随机数种子方式
    elmentui表单重置及出现的问题
    数据安全与个人隐私:美国人的焦虑与变化
  • 原文地址:https://blog.csdn.net/qq_38628046/article/details/126178298