一文理解SpringBean生命周期之PostConstruct、PreDestroy详解( 二 )


一文理解SpringBean生命周期之PostConstruct、PreDestroy详解

文章插图
 
这个方法关键是上面的两步,第一步找出所有注解的方法,第二步执行对应的方法,第二步比较简单,就是调用了反射操作,我们重点关注在第一步findLifecycleMetadata方法 。
/** * 查找指定类型的生命周期元数据. */private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {// lifecycleMetadataCache为空,则重新创建生命周期元数据.if (this.lifecycleMetadataCache == null) {// HAppens after deserialization, during destruction...return buildLifecycleMetadata(clazz);}// 采用双重检查锁机制来进行快速检查,尽量减少对锁的使用 。// 首先进行快速检查,只需最少的锁竞争.// Quick check on the concurrent map first, with minimal locking.LifecycleMetadata metadata = https://www.isolves.com/it/cxkf/kj/2022-06-21/this.lifecycleMetadataCache.get(clazz);if (metadata == null) {// 加锁处理synchronized (this.lifecycleMetadataCache) {metadata = this.lifecycleMetadataCache.get(clazz);if (metadata == null) {// 关键方法,构建LifecycleMetadatametadata = buildLifecycleMetadata(clazz);this.lifecycleMetadataCache.put(clazz, metadata);}return metadata;}}return metadata; }查看关键的方法buildLifecycleMetadata的源码如下:
/** * 创建生命周期元数据. */private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {// 判断当前Bean是否包含@PostContruct,@PreDestroy,如果不包含,直接返回if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {return this.emptyLifecycleMetadata;}// 初始化相关元数据List<LifecycleElement> initMethods = new ArrayList<>();// 销毁相关的元数据List<LifecycleElement> destroyMethods = new ArrayList<>();Class<?> targetClass = clazz;do {final List<LifecycleElement> currInitMethods = new ArrayList<>();final List<LifecycleElement> currDestroyMethods = new ArrayList<>();// 遍历类中的methodsReflectionUtils.doWithLocalMethods(targetClass, method -> {// 判断方法是有@PostConstruct注解if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {LifecycleElement element = new LifecycleElement(method);currInitMethods.add(element);if (logger.isTraceEnabled()) {logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);}}// 判断方法是有@PreDestroy注解if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {currDestroyMethods.add(new LifecycleElement(method));if (logger.isTraceEnabled()) {logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);}}});initMethods.addAll(0, currInitMethods);destroyMethods.addAll(currDestroyMethods);// 查找父类targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :new LifecycleMetadata(clazz, initMethods, destroyMethods)); }复制代码该方法主要是遍历bean对应的class以及父class中包含@PostConstruct、@PreDestroy注解的方法,构建出
LifecycleMetadata对象 。
有一个问题,上面查找其实用的都是initAnnotationType、@PostConstruct、@PreDestroy属性,那他们是在上面时候设置为@PostConstruct、@PreDestroy呢?
我们可以看父类
CommonAnnotationBeanPostProcessor的构造方法,它在实例化CommonAnnotationBeanPostProcessor这个bean的时候设置 。
一文理解SpringBean生命周期之PostConstruct、PreDestroy详解

文章插图
 
public CommonAnnotationBeanPostProcessor() {setOrder(Ordered.LOWEST_PRECEDENCE - 3);// 设置PostConstructsetInitAnnotationType(PostConstruct.class);setDestroyAnnotationType(PreDestroy.class);ignoreResourceType("javax.xml.ws.WebServiceContext");// java.naming module present on JDK 9+?if (jndiPresent) {this.jndiFactory = new SimpleJndiBeanFactory();} }何时实例化CommonAnnotationBeanPostProcessor那么
CommonAnnotationBeanPostProcessor这个Bean处理器是在什么时候装载到容器中呢?只有它装载到容器中后,才会执行对应的方法 。
一文理解SpringBean生命周期之PostConstruct、PreDestroy详解

文章插图
 
  1. 在创建容器的时候,会创建所有的BeanPostProcessors Bean 。
  2. 在创建CommonAnnotationBeanPostProcessor这个Bean的时候,就会调用对应的构造方法,设置对应的PostConstruct注解 。
大家可以看下这篇文章了解BeanPostProcessor的详细过程SpringBoot扩展点——一文掌握BeanPostProcessor家族
那又是什么时候把


推荐阅读