您现在的位置是:首页 >技术交流 >Spring 填充属性和初始化流程源码剖析及扩展实现网站首页技术交流
Spring 填充属性和初始化流程源码剖析及扩展实现
前言
在上一篇博文
讲解 Spring 实例化的不同方式及相关生命周期源码剖析 介绍了 Spring 实例化的不同方式,本文主要围绕实例化过后对象的填充属性和初始化过程进行详细流程剖析
回顾前言知识,doCreateBean->createBeanInstance,通过 Supplier 接口、FactoryMethod、构造函数反射 invoke,创建好实例对象
填充属性
前置工作
之前在 DefaultListableBeanFactory#preInstantiateSingletons 方法
冻结了所有 BeanDefinition 不可再被修改,为了确保实例化能够正常完成,但是现在已经到了初始化阶段,允许最后一次修改:合并 BeanDefinition 信息.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// MergedBeanDefinitionPostProcessor 后置处理器修改合并 bean 定义
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
实现了 MergedBeanDefinitionPostProcessors 接口的 BeanPostProcessor 到指定的 beanDefinition 中,执行 postProcessMergedBeanDefinition 方法
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
Spring 通过此方法找出所有需要注入的字段,同时做缓存;在这里主要介绍它下面三个实现类:InitDestroyAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor
从 Java 生成的类图中可以看出,CommonAnnotationBeanPostProcessor 继承至 InitDestroyAnnotationBeanPostProcessor,下面,我们再通过一个结构图来看它们各自负责作什么事情:
- InitDestroyAnnotationBeanPostProcessor: CommonAnnotationBeanPostProcessor 父类,该类主要处理的是初始化、销毁的逻辑,用于处理 @PostConstruct、@PreDestroy 注解的,在这个阶段只是提前将该阶段的注解元数据扫描出来加入到缓存集合中,在后续调用 postProcessBeforeInitialization 方法时触发标注了对应注解的方法,一般我们使用这两个注解,是为了注入我们业务中想要单独使用的东西而在 Spring 设计范围内无法为我们所提供的时候,比如:在容器启动时先刷新一次我们的业务重试表,对数据进行一次预处理或调用属性时想通过静态的方式进行调用时,就可以在 @PostConstruct 标注的方法内帮我们完成工作.
- CommonAnnotationBeanPostProcessor:该类用于处理 @Resource 注解,它根据 beanName 进行注入,一般我们标注在要注入的实例属性上;当它标注在方法上进行注入时,若没有参数,标注 @Resource 会抛出异常
@Resource annotation requires a single-arg method
比如:下面这么写,它就会在注入时出现这个错误
public class A {
@Resource
public B b() {
return new B();
}
}
- AutowiredAnnotationBeanPostProcessor:该类用于处理 @Autowired 和 @Value 注解,在解析阶段,分别会有一个属性节点内部类:AutowiredFieldElement、方法节点内部类:AutowiredMethodElement 为属性完成赋值工作.
以上三个类处理 postProcessMergedBeanDefinition 方法时,先构建好自动装配的属性、方法元数据存入缓存中,再对其进行检查后更新 BeanDefinition 属性,也就是追加元素> RootBeanDefinition#externallyManagedConfigMembers 集合中
实际干活
一切的前置工作做完以后,接下来就是触发实际干活的工作了