且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

【String注解驱动开发】你真的了解@PostConstruct注解和@PreDestroy注解吗?

更新时间:2022-09-05 08:51:26

@PostConstruct注解

@PostConstruct注解好多人以为是Spring提供的。其实是Java自己的注解。我们来看下@PostConstruct注解的源码,如下所示。

package javax.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}

从源码可以看出,@PostConstruct注解是Java中的注解,并不是Spring提供的注解。

@PostConstruct注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。

通常我们会是在Spring框架中使用到@PostConstruct注解,该注解的方法在整个Bean初始化中的执行顺序:

Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)。

@PreDestroy注解

@PreDestroy注解同样是Java提供的,看下源码,如下所示。

package javax.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}

被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。执行顺序如下所示。

调用destroy()方法->@PreDestroy->destroy()方法->bean销毁。

总结:@PostConstruct,@PreDestroy是Java规范JSR-250引入的注解,定义了对象的创建和销毁工作,同一期规范中还有注解@Resource,Spring也支持了这些注解。

案例程序

对@PostConstruct注解和@PreDestroy注解有了简单的了解之后,接下来,我们就写一个简单的程序来加深对这两个注解的理解。

我们创建一个Cat类,如下所示。

package io.mykit.spring.plugins.register.bean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
 * @author binghe
 * @version 1.0.0
 * @description 测试@PostConstruct注解和@PreDestroy注解
 */
public class Cat {
    public Cat(){
        System.out.println("Cat类的构造方法...");
    }
    public void init(){
        System.out.println("Cat的init()方法...");
    }
    @PostConstruct
    public void postConstruct(){
        System.out.println("Cat的postConstruct()方法...");
    }
    @PreDestroy
    public void preDestroy(){
        System.out.println("Cat的preDestroy()方法...");
    }
    public void destroy(){
        System.out.println("Cat的destroy()方法...");
    }
}

可以看到,在Cat类中,我们提供了构造方法,init()方法、destroy()方法,使用 @PostConstruct注解标注的postConstruct()方法和只用@PreDestroy注解标注的preDestroy()方法。接下来,我们在AnimalConfig类中使用@Bean注解将Cat类注册到Spring容器中,如下所示。

@Bean(initMethod = "init", destroyMethod = "destroy")
public Cat cat(){
    return new Cat();
}

接下来,在BeanLifeCircleTest类中新建testBeanLifeCircle04()方法进行测试,如下所示。

@Test
public void testBeanLifeCircle04(){
    //创建IOC容器
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnimalConfig.class);
    //关闭IOC容器
    context.close();
}

运行BeanLifeCircleTest类中的testBeanLifeCircle04()方法,输出的结果信息如下所示。

Cat类的构造方法...
Cat的postConstruct()方法...
Cat的init()方法...
Cat的preDestroy()方法...
Cat的destroy()方法...

从输出的结果信息中,可以看出执行的顺序是:构造方法 -> @PostConstruct -> init()方法 -> @PreDestroy -> destroy()方法。