SpringBoot @PostConstruct和@PreDestroy的使用说明

编辑: admin 分类: java 发布时间: 2021-12-03 来源:互联网
目录
  • 1. @PostConstruct
    • 1.1 概述
    • 1.2 验证执行顺序
  • 2. @PreDestroy

    1. @PostConstruct

    1.1 概述

    @PostConstruct标记在方法上,在当前类的实例加入到容器之前,会先执行@PostConstruct标记的方法。它的执行顺序是这样的:

    • 先执行当前类的构造函数
    • 然后执行@Autowired标记对象的初始化
    • 最后执行@PostConstruct标记的方法
    • 如果没有抛出异常,则该对象加入Spring管理容器

    1.2 验证执行顺序

    创建一个空的Spring Boot项目,这步不演示了

    创建TestComponent

    @Component
    public class TestComponent {
        public TestComponent(){
            System.out.println("TestComponent 构造函数");
        }
        @PostConstruct
        public void init(){
            System.out.println("TestComponent PostConstruct");
        }
    }
    

    创建MyService

    public interface MyService {
        void Hello(String name);
    }
    

    创建MyServiceImpl

    @Service
    public class MyServiceImpl implements MyService {
        public MyServiceImpl(){
            System.out.println("MyServiceImpl 构造函数");
        }
        @PostConstruct
        public void init(){
            System.out.println("MyServiceImpl PostConstruct");
        }
        @Override
        public void Hello(String name) {
            System.out.println("Hello " + name);
        }
    }
    

    运行项目,看下输出结果。

    TestComponent和MyServiceImpl分别独自初始化,构造函数优先执行

    请记住这个执行顺序

    TestComponent 构造函数

    TestComponent PostConstruct

    MyServiceImpl 构造函数

    MyServiceImpl PostConstruct

    还没完,改一下TestComponent,加入引用MyService

        @Autowired
        private MyService myService;
    

    再执行一下,看看结果有什么变化

    TestComponent 构造函数

    MyServiceImpl 构造函数

    MyServiceImpl PostConstruct

    TestComponent PostConstruct

    MyServiceImpl执行顺序往前移动了,证明@Autowired顺序在@PostConstruct之前

    因此,如果要在TestComponent初始化的时候调用MyService方法,要写在@PostConstruct内部,不能在构造函数处理(这时候MyServiceImpl还没初始化,会抛出空指针异常)

    @Component
    public class TestComponent {
        @Autowired
        private MyService myService;
        public TestComponent(){
            System.out.println("TestComponent 构造函数");
            //写在这里必定抛出异常,此时 myService == null
    		//myService.Hello("张三");
        }
        @PostConstruct
        public void init(){
            System.out.println("TestComponent PostConstruct");
            //在这里调用MySerice方法才正确
            myService.Hello("张三");
        }
    }
    

    2. @PreDestroy

    首先,来看下Java Doc对这个注解的说明

    在这里插入图片描述

    1: 在对象实例被容器移除的时候,会回调调用@PreDestroy标记的方法

    2: 通常用来释放该实例占用的资源

    修改上面的TestComponent代码,加上@PreDestroy代码

        @PreDestroy
        public void destroy(){
            System.out.println("TestComponent 对象被销毁了");
        }
    

    修改Application main方法,启动10秒后退出程序

    @SpringBootApplication
    public class AnnotationTestApplication {
        public static void main(String[] args) {
            ConfigurableApplicationContext ctx = SpringApplication.run(AnnotationTestApplication.class, args);
    		
            try {
                Thread.sleep(10 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ctx.close();
        }
    }
    

    启动程序,查看输出信息

    程序退出时会销毁对象,所以会触发我们刚写的@PreDestroy方法,测试通过。

    在这里插入图片描述

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。

    【本文由:日本cn2服务器 提供 转载请保留URL】