0
点赞
收藏
分享

微信扫一扫

Spring注解:@PostConstruct和@PreDestroy

Mhhao 2021-10-15 阅读 70
技术分享

前面说,在Spring管理Bean生命周期的过程中,可以自定义初始化及销毁方法,主要有@Bean注解中加入init-method和destroy-method属性的方式、还有Spring提供的InitializingBean和DisposableBean接口的方式。那么在Java规范中,也提供类似这样的方式,就是@PostConstruct和@PreDestroy注解,意思是在对象创建之后和在对象销毁之前。

@PostConstruct
/**
 * The PostConstruct annotation is used on a method that needs to be executed
 * after dependency injection is done to perform any initialization. This
 * method MUST be invoked before the class is put into service. This
 * annotation MUST be supported on all classes that support dependency
 * injection. The method annotated with PostConstruct MUST be invoked even
 * if the class does not request any resources to be injected. Only one
 * method can be annotated with this annotation. The method on which the
 * PostConstruct annotation is applied MUST fulfill all of the following
 * criteria:
 * <p>
 * <ul>
 * <li>The method MUST NOT have any parameters except in the case of
 * interceptors in which case it takes an InvocationContext object as
 * defined by the Interceptors specification.</li>
 * <li>The method defined on an interceptor class MUST HAVE one of the
 * following signatures:
 * <p>
 * void &#060;METHOD&#062;(InvocationContext)
 * <p>
 * Object &#060;METHOD&#062;(InvocationContext) throws Exception
 * <p>
 * <i>Note: A PostConstruct interceptor method must not throw application
 * exceptions, but it may be declared to throw checked exceptions including
 * the java.lang.Exception if the same interceptor method interposes on
 * business or timeout methods in addition to lifecycle events. If a
 * PostConstruct interceptor method returns a value, it is ignored by
 * the container.</i>
 * </li>
 * <li>The method defined on a non-interceptor class MUST HAVE the
 * following signature:
 * <p>
 * void &#060;METHOD&#062;()
 * </li>
 * <li>The method on which PostConstruct is applied MAY be public, protected,
 * package private or private.</li>
 * <li>The method MUST NOT be static except for the application client.</li>
 * <li>The method MAY be final.</li>
 * <li>If the method throws an unchecked exception the class MUST NOT be put into
 * service except in the case of EJBs where the EJB can handle exceptions and
 * even recover from them.</li></ul>
 * @since Common Annotations 1.0
 * @see javax.annotation.PreDestroy
 * @see javax.annotation.Resource
 */
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}

PostConstruct注释用于在完成依赖注入以执行任何初始化之后需要执行的方法。必须在类投入服务之前调用此方法。支持依赖注入的所有类都必须支持此批注。

@PreDestroy
/**
 * The PreDestroy annotation is used on methods as a callback notification to
 * signal that the instance is in the process of being removed by the
 * container. The method annotated with PreDestroy is typically used to
 * release resources that it has been holding. This annotation MUST be
 * supported by all container managed objects that support PostConstruct
 * except the application client container in Java EE 5. The method on which
 * the PreDestroy annotation is applied MUST fulfill all of the following
 * criteria:
 * <p>
 * <ul>
 * <li>The method MUST NOT have any parameters except in the case of
 * interceptors in which case it takes an InvocationContext object as
 * defined by the Interceptors specification.</li>
 * <li>The method defined on an interceptor class MUST HAVE one of the
 * following signatures:
 * <p>
 * void &#060;METHOD&#062;(InvocationContext)
 * <p>
 * Object &#060;METHOD&#062;(InvocationContext) throws Exception
 * <p>
 * <i>Note: A PreDestroy interceptor method must not throw application
 * exceptions, but it may be declared to throw checked exceptions including
 * the java.lang.Exception if the same interceptor method interposes on
 * business or timeout methods in addition to lifecycle events. If a
 * PreDestroy interceptor method returns a value, it is ignored by
 * the container.</i>
 * </li>
 * <li>The method defined on a non-interceptor class MUST HAVE the
 * following signature:
 * <p>
 * void &#060;METHOD&#062;()
 * </li>
 * <li>The method on which PreDestroy is applied MAY be public, protected,
 * package private or private.</li>
 * <li>The method MUST NOT be static.</li>
 * <li>The method MAY be final.</li>
 * <li>If the method throws an unchecked exception it is ignored except in the
 * case of EJBs where the EJB can handle exceptions.</li>
 * </ul>
 *
 * @see javax.annotation.PostConstruct
 * @see javax.annotation.Resource
 * @since Common Annotations 1.0
 */

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}

PreDestroy注释在方法上用作回调通知,以表示实例正在被容器移除。用PreDestroy注释的方法通常用于释放它一直持有的资源。

自定义Bean,添加@PostConstruct和@PreDestroy注解
@Component
public class Student {

    public Student() {
        System.out.println("Student 构造器");
    }

    @PostConstruct
    public void init() {
        System.out.println("Student 对象创建之后");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("Student 对象销毁之前");
    }
}

测试

@Test
public void testBean() {
    AnnotationConfigApplicationContext applicationContext =
            new AnnotationConfigApplicationContext(MainConfig.class);
    System.out.println("容器创建完成");
    //关闭容器
    applicationContext.close();
    System.out.println("容器关闭");
}
Student 构造器
Student 对象创建之后
容器创建完成
......
Student 对象销毁之前
容器关闭

至于@PostConstruct和@PreDestroy的定义,Java中并没有解释为初始化和销毁,顾名思义,PostConstruct在构造器之后,PreDestroy在销毁之前,实际上在Spring管理Bean的生命周期中,@PostConstruct和@PreDestroy可以自定义的管理Bean的初始化和销毁这两个阶段。

在Spring中Constructor、@Autowired、@PostConstruct的执行顺序

其实从依赖注入的字面意思就可以知道,要将对象p注入到对象a,那么首先就必须得生成对象p与对象a,才能执行注入。所以,如果一个类A中有个成员变量p被@Autowired注解,那么@Autowired注入是发生在A的构造方法执行完之后的。

如果想在生成对象时候完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么就无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。

Constructor >> @Autowired >> @PostConstruct

举报

相关推荐

0 条评论