注解@PostConstruct分析
作用
1.注解@PostConstruct可以添加在类的方法上面,如果这个类被IOC容器托管,那么在对Bean进行初始化前的时候会调用被这个注解修饰的方法
被定义在哪里?
1.被定义在了CommonAnnotationBeanPostProcessor类,这个类是InitDestroyAnnotationBeanPostProcessor类的子类,也实现了InstantiationAwareBeanPostProcessor接口(BeanDefinition的后置处理接口)。代码展示:
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
2.故在这个CommonAnnotationBeanPostProcessor类实例化的时候注解就会被定义下来。
在何处被扫描?
1.在BeanDefinition的后置处理时调用 postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)进行扫描
2.在初始化前中调用处理器InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization方法进行扫描
汇总:
两处扫描的本质都是调用了 LifecycleMetadata findLifecycleMetadata(Class<?> clazz)方法(位于InitDestroyAnnotationBeanPostProcessor类里面),
扫描方法分析
1.findLifecycleMetadata方法分析:
说明:
1)判断缓存有没有构建,没有构建则调用构建Metadata对象的方法
2)缓存构建了,就去缓存里面寻找,没找到就调用构建Metadata对象的方法,把拿回来的对象存入缓存中
代码展示:
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
if (this.lifecycleMetadataCache == null) {
return buildLifecycleMetadata(clazz);
}
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
2.buildLifecycleMetadata方法分析:
说明:
1)主要应用类反射机制的概念,doWithLocalMethods通过类获取所有方法,然后利用反射机制构建调用对象
2)LifecycleMetadata对象便是包含了该类的所有的初始化方法和销毁方法
代码展示:
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
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<>(); //doWithLocalMethods,深入源码其实可知是通过类对象取出所有的方法,逐一进行调用lambda表达式的方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//判断初始化方法
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
}
//判断销毁方法
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
}
}); //根据继承关系故会有父类要比子类先构造,子类要比父类先销毁
//所以这里采用头插法
initMethods.addAll(0, currInitMethods);
//这里会往末尾存放
destroyMethods.addAll(currDestroyMethods);
//寻找父类
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class); return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}
在何处被调用?(过程分析)
1.既然是在初始化前的处理器中调用,而且源于InitDestroyAnnotationBeanPostProcessor这个处理器会在初始化前这个步骤中执行@PostConstruct的方法
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//这一步是寻找
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
//这一步是调用
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
2.基于反射机制调用方法对象来调用类对象的方法:
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
Collection<LifecycleElement> initMethodsToIterate = (checkedInitMethods != null ? checkedInitMethods : this.initMethods);
if (!initMethodsToIterate.isEmpty()) {
for (LifecycleElement element : initMethodsToIterate) {
element.invoke(target);
}
}
}
postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
注解@PostConstruct分析的更多相关文章
- 【JPA】注解@PostConstruct、@PreDestroy
从Java EE5规范开始,Servlet增加了两个影响Servlet生命周期的注解@PostConstruct和@PreConstruct.这两个注解被用来修饰一个非静态的void()方法,而且这个 ...
- uboot-的start.S详细注解及分析
原文地址:uboot-的start.S详细注解及分析 作者:zhouyg11 大多数bootloader都分为stage1和stage2两部分,u-boot也不例外.依赖于CPU体系结构的代码(如设备 ...
- Spring注解@PostConstruct与@PreDestroy
关于在spring 容器初始化 bean 和销毁前所做的操作定义方式有三种: 第一种:通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作 第二 ...
- servlet注解@PostConstruct与@PreDestroy
从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解(Annotion):@PostConstruct和@PreDestroy.这两个注解被用来修饰一个非静态的vo ...
- 注解@PostConstruct与@PreDestroy讲解及实例
从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解(Annotion):@PostConstruct和@PreDestroy.这两个注解被用来修饰一个非静态的vo ...
- 注解@PostConstruct与@PreDestroy 特性说明
简介 Java EE5 引入了@PostConstruct和@PreDestroy这两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作.此文主要说明@PostCons ...
- Spring 注解详细分析解释有实例
概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...
- springboot - Constructor、@Autowired、@PostConstruct分析
1.Constructor 构造方法 2.@Autowired 依赖注入 3.@PostConstruct 在依赖注入完成后被自动调用 4. 三者的顺序: 从依赖注入的字面意思就可以知道,要将对象p注 ...
- 注解@PostConstruct与@PreDestroy详解及实例
Java EE5 引入了@PostConstruct和@PreDestroy这两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作.此文主要说明@PostConstru ...
随机推荐
- HashMap的实现原理?如何保证HashMap线程安全?
A:HashMap简单说就是它根据建的hashcode值存储数据的,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历的顺序是不确定的. B:HashMap基于哈希表,底层结构由数组来实 ...
- 加班?不存在的啦~Python处理Excel,学会这十四个方法,工作量减少大半
现在Python横行的年代,财务.人事.行政等等岗位多少得学点Python,省事又不费脑!所有操作都用Python自动实现, 加班?不存在的! excel和python其实都是工具,不要也不用拿去做对 ...
- 【Azure Developer】记录一次使用Java Azure Key Vault Secret示例代码生成的Jar包,单独运行出现 no main manifest attribute, in target/demo-1.0-SNAPSHOT.jar 错误消息
问题描述 创建一个Java Console程序,用于使用Azure Key Vault Secret.在VS Code中能正常Debug,但是通过mvn clean package打包为jar文件后, ...
- 步态识别《GaitSet: Regarding Gait as a Set for Cross-View Gait Recognition》2018 CVPR
Motivation: 步态可被当作一种可用于识别的生物特征在刑侦或者安全场景发挥重要作用.但是现有的方法要么是使用步态模板(能量图与能量熵图等)导致时序信息丢失,要么是要求步态序列连续,导致灵活性差 ...
- Vue3 项目实战
使用Vue3 开发一个小米商城 业务流程 登录---> 产品首页--->产品站--->产品详情 购物车--->订单确认--->订单支付--->订单列表 业务开发流程 ...
- 要想不踩SaaS那些坑,得先了解“SaaS架构”
摘要:围绕当下许多企业青睐的SaaS应用开发,华为云开发者技术服务工程师程泽在DTT首期带来主题为 <SaaS云原生应用典型架构> 的DTT首期直播分享. 本文分享自华为云社区<DT ...
- 通过jmeter压测surging
前言 surging是异构微服务引擎,提供了模块化RPC请求通道,引擎在RPC服务治理基础之上还提供了各种协议,并且还提供了stage组件,以便针对于网关的访问, 相对于功能,可能大家更想知道能承受多 ...
- Template -「平衡树」
Fhq-Treap. // Fhq-Treap const int MAXN = 1e5 + 5; struct Fhq_Treap { #define Lson Tr[p].l #define Rs ...
- Solution -「Local 11145」诗意狗
0x01 前置芝士 树形结构?贪心?思维?眼睛? 好有趣... link 0x02 题目大意:给你一颗有 \(n\) 个节点的树,你需要尽可能多的删掉边,使得剩下的图中有 \(k\) 个点满足互相能走 ...
- 74HC595驱动(并转串,fpga与时钟匹配,fpga与外部芯片的连接注意事项)
上一次设计的动态扫描数码管显示电路模型如上,这是一个32位并行数据[31:0]disp_num选通输出并行数据[7:0]select和[7:0]段选的电路.因此需要输出16个信号 而在开发板上的电路与 ...