@Resource、@PostConstruct、@PreDestroy注解解析

CommonAnnotationBeanPostProcessor解析@Resource、@PostConstruct、@PreDestroy注

CommonAnnotationBeanPostProcessor解析@Resource、@PostConstruct、@PreDestroy注解

我们在之前的文章分析里已经知道AnnotationConfigServletWebServerApplicationContext在初始化时会实例化一些后置处理器,其中就包括CommonAnnotationBeanPostProcessor处理器,通过之前我们分析@Autowired注解解析流程知道比较关键的两个流程是通过MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()对需要处理的注解进行解析并封装成InjectionMetadata,然后通过InstantiationAwareBeanPostProcessor.postProcessProperties()方法对InjectionMetadata进行处理,把相应的对象或value找到并填充到属性中。而CommonAnnotationBeanPostProcessor

跟AutowiredAnnotationBeanPostProcessor继承体系是一样的,流程也差不多,只是在处理细节上稍微有一些区别。

CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition方法

@Resource、@PostConstruct、@PreDestroy注解解析

首先调了父类的postProcessMergedBeanDefinition方法,而他的父类是InitDestroyAnnotationBeanPostProcessor,所以先看父类的实现逻辑:

InitDestroyAnnotationBeanPostProcessor.InitDestroyAnnotationBeanPostProcessor方法

@Resource、@PostConstruct、@PreDestroy注解解析

代码结构几乎是一样的,那么我们重点关注的是InitDestroyAnnotationBeanPostProcessor处理的是哪些注解以及在什么时候开始注解逻辑。

@Resource、@PostConstruct、@PreDestroy注解解析

调用细节这里就不多说了,跟@Autowired流程一样,从buildLifecycleMetadata方法可以看出:主要是解析initAnnotationType和destroyAnnotationType两个注解,然后封装成LifecycleElement和LifecycleMetadata,需要注意的是被修饰的方法必须是无参方法,那么initAnnotationType和destroyAnnotationType具体代表是哪两个注解呢

initAnnotationType和destroyAnnotationType具体代表是哪两个注解呢

@Resource、@PostConstruct、@PreDestroy注解解析

从CommonAnnotationBeanPostProcessor的构造方法可以看出,initAnnotationType就是@PostConstruct注解,destroyAnnotationType就是@PreDestroy注解。initAnnotationType和destroyAnnotationType这两个注解的含义以及被这两个注解的解析过程已经了解了,那么什么时候对封装后的LifecycleElement和LifecycleMetadata进行处理呢?

LifecycleElement和LifecycleMetadata处理入口以及流程

这个流程就要回到bean的实例化流程里:通过doCreateBean方法对bean实例化时会先用无参构造器或工厂方法进行实例化类,然后用populateBean方法对实例化对象进行属性的填充,填充完之后用initializeBean方法对bean实例化时需要调用的一些初始化方法进行最后的调用,然后就算实例化完成了,在就注册了一些bean销毁时调用的后置处理器(DestructionAwareBeanPostProcessor)。而我们的@PostConstruct就是在initializeBean方法中处理,@PreDestroy在bean销毁时DestructionAwareBeanPostProcessor.postProcessBeforeDestruction方法中处理。

initializeBean方法处理@PostConstruct

@Resource、@PostConstruct、@PreDestroy注解解析

  1. 对BeanNameAware、BeanClassLoaderAware、BeanFactoryAware中的方法进行调用
  2. 调用BeanPostProcessor.postProcessBeforeInitialization()方法
  3. 调用InitializingBean.afterPropertiesSet()方法和bean的自定义init方法
  4. 调用BeanPostProcessor.postProcessAfterInitialization()方法

而我们的@PostConstruct就是在BeanPostProcessor.postProcessBeforeInitialization()方法中被处理。

InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()方法

@Resource、@PostConstruct、@PreDestroy注解解析

@Resource、@PostConstruct、@PreDestroy注解解析

@Resource、@PostConstruct、@PreDestroy注解解析

可以看到实际上就是使用了反射调用了@PostConstruct修饰的方法。

InitDestroyAnnotationBeanPostProcessor.postProcessBeforeDestruction()方法

@Resource、@PostConstruct、@PreDestroy注解解析

@Resource、@PostConstruct、@PreDestroy注解解析

@Resource、@PostConstruct、@PreDestroy注解解析

可以看到实际上就是使用了反射调用了@PreDestroy修饰的方法。

至此,InitDestroyAnnotationBeanPostProcessor对于@PostConstruct和@PreDestroy的处理逻辑就处理完了。我们接着看CommonAnnotationBeanPostProcessor中的postProcessMergedBeanDefinition()逻辑。

CommonAnnotationBeanPostProcessor.findResourceMetadata方法

@Resource、@PostConstruct、@PreDestroy注解解析

@Resource、@PostConstruct、@PreDestroy注解解析

resourceAnnotationTypes这个属性是使用下面这个static代码块初始化的

@Resource、@PostConstruct、@PreDestroy注解解析

而@Resource注解会被封装成ResourceElement对象。

ResourceElement.getResourceToInject方法

@Resource、@PostConstruct、@PreDestroy注解解析

可以看到@Resource默认是name进行注入,如果@Resource设置了name则以设置的为准否则以属性的变量名为准。

总结:

  1. CommonAnnotationBeanPostProcessor实际上处理了@PostConstruct、@PreDestroy和@Resource注解,但@PostConstruct、@PreDestroy是交给父类DestructionAwareBeanPostProcessor来处理。
  2. @PostConstruct是在bean已经实例化且属性也已经填充完后在initializeBean方法中进行处理,@PostConstruct在bean被销毁时处理
  3. @Resource注入时是按name来注入,name优先取@Resource中的name否则取变量名。而@Autowired默认是按classType注入,当找到多个classType类时按变量名注入。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/10321.html

(0)
上一篇 2023年 4月 22日 下午11:58
下一篇 2023年 4月 22日 下午11:58

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信