1 @PostStruct
1.1 概述
定义及用途
@PostConstruct(javax.annotation.PostConstruct)
注解好多人以为是Spring提供的。而实际上是Java自身的注解。
Java中该注解的说明:
@PostConstruct
,该注解被用来修饰一个非静态的void()
方法。被@PostConstruct
修饰的方法会在服务器加载Servlet
的时候运行,并且只会被服务器执行一次。
PostConstruct
在构造函数之后执行,init()方法之前执行。
通常地,在Spring框架中也会使用到
@PostConstruct
注解。那么,整个Bean
初始化的执行顺序为:
- step1 Constructor(构造方法)
- step2 @Autowired(依赖注入)
- step3 @PostConstruct(注释的方法)
应用场景
- 场景1:在静态方法中调用spring
依赖注入
的Bean中的方法。
package com.example.studySpringBoot.util;
import com.example.studySpringBoot.service.MyMethorClassService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class MyUtils {
private static MyUtils staticInstance = new MyUtils();
@Autowired
private MyMethorClassService myService;
@PostConstruct
public void init(){
staticInstance.myService = myService;
}
public static Integer invokeBean(){
return staticInstance.myService.add(10,20);
}
}
源码
package javax.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface PostConstruct {
}
使用示例
![](/i/l/?n=23&i=blog/1173617/202301/1173617-20230115173501614-2090860694.png)
1.2 发展历程:[JDK 1.6-1.8]
1.2.1 始于JDK1.6 Annotations
Common Annotations 原本是
Java EE 5.0(JSR 244)规范
的一部分,现在SUN
把它的一部分放到了Java SE 6.0
中。随着Annotation
元数据功能加入到Java SE 5.0
里面,很多Java 技术都会用Annotation
部分代替XML
文件来配置运行参数。以下列举Common Annotations 1.0里面的几个Annotations:
-
@Generated:用于标注生成的源代码
-
@Resource: 用于标注所依赖的资源,容器据此注入外部资源依赖,有基于字段的注入和基于setter方法的注入两种方式 。
-
@Resources:同时标注多个外部依赖,容器会把所有这些外部依赖注入
-
@PostConstruct:标注当容器注入所有依赖之后运行的方法,用来进行依赖注入后的初始化工作,只有一个方法可以标注为PostConstruct 。
-
@PreDestroy:当对象实例将要被从容器当中删掉之前,要执行的回调方法要标注为PreDestroy 作者:苦逼码农xisdn https://www.bilibili.com/read/cv7666575 出处:bilibili
1.2.2 弃于JDK1.9,止于JDK1.11
-
JDK 在
Java 9
中已被弃用,而在Java 11
中已被删除 -
解决方法:主动引入第三方JAR包
<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
1.3 原理分析
JDK提供的@PostConstruct注解,Spring是如何实现的呢?
需要先学习下BeanPostProcessor这个接口:
import org.springframework.beans.factory.config;
import ...
public interface BeanPostProcessor {
/**
* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
*
* 任何Bean实例化,并且Bean已经populated(填充属性) 就会回调这个方法
*
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
*
* 任何Bean实例化,并且Bean已经populated(填充属性) 就会回调这个方法
*
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
那Spring
初始化是那里回调这些方法呢?
AbstractApplicationContext.finishBeanFactoryInitialization(...);
beanFactory.preInstantiateSingletons();
DefaultListableBeanFactory.getBean(beanName);
AbstractBeanFactory.doGetBean();
AbstractAutowireCapableBeanFactory.createBean(....)
populateBean(beanName, mbd, instanceWrapper);
initializeBean(...)
//调用BeanPostProcessor.postProcessBeforeInitialization()方法
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
//调用BeanPostProcessor.postProcessBeforeInitialization()方法
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
BeanPostProcessor
有个实现类CommonAnnotationBeanPostProcessor
,就是专门处理@PostConstruct
、@PreDestroy注解。
CommonAnnotationBeanPostProcessor的父类InitDestroyAnnotationBeanPostProcessor()
InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()
InitDestroyAnnotationBeanPostProcessor.findLifecycleMetadata()
// 组装生命周期元数据
InitDestroyAnnotationBeanPostProcessor.buildLifecycleMetadata()
// 查找@PostConstruct注释的方法
InitDestroyAnnotationBeanPostProcessor.initAnnotationType
// 查找@PreDestroy注释方法
InitDestroyAnnotationBeanPostProcessor.destroyAnnotationType
// 反射调用
metadata.invokeInitMethods(bean, beanName);
X 参考文献
- Java程序员必备基础:JDK 5-15都有哪些经典新特性 - bilibili
- jdk6新特性 - 码农家园
- JDK新特性(JDK6) [转载] - 蜂巢驻点
- 无法在Java 11中使用@PostConstruct和@PostDestroy - CSDN 【推荐】
- Spring PostConstruct and PreDestroy Annotations - baeldung 【推荐】