dcddc

西米大人的博客

0%

系统学习Spring源码-bean加载

前言

所谓 bean 加载,即创建 bean 实例,由 bean 工厂实现,包括 bean 实例化、依赖注入和初始化过程

入口:org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)

bean 加载有如下几个关键点需要注意。

关于 bean 作用域

  • 常见的 bean 作用域有单例 singleton 和原型 prototype,单例 bean 需要保证全局唯一,原型 bean 每次加载都生成新的实例
  • 单例 bean 全局唯一性使用 bean 工厂的 HashMap 缓存保证

关于循环依赖

Spring 解决循环依赖使用 EarlyReference 机制,能利用该机制的就允许存在循环依赖,否则不允许,bean 加载阶段抛异常

  • 对于单例 bean,Spring 支持 setter 依赖注入产生的循环依赖,不支持构造器注入产生的循环依赖,在 bpp 钩子函数里被代理的 bean 也不支持循环依赖
    • Spring 解决单例 bean 的 setter 注入循环依赖使用earlyReference(实例化完成但还未初始化的 bean)机制,通过 earlySingletonObjectsMap 提前暴露 bean 的 earlyReference,依赖它的 beans 注入的是 earlyReference
    • 对于构造器注入产生的循环依赖,bean 实例化的前提就是循环依赖的 beans 也加载完成。所以加载依赖 beans 不能用到 earlyReference 机制,造成递归加载 bean 直到堆栈溢出,所以 Spring 不支持构造器注入的循环依赖。Spring 通过将加载中的 beanName 加入 singletonsCurrentlyInCreationSet 来检测是否存在这种场景的循环依赖,一旦 bean 未实例化完成(拿不到 earlyReference)又需要再次加载,就抛异常
    • 如果当 bean 在实例化完成后又在 bpps 的一些钩子函数里被代理,则依赖它的 beans 无法注入真正的 bean 实例。因此 Spring 不支持在 bpp 钩子函数里被代理的 bean 存在循环依赖,一旦发现会抛异常
  • 原型 bean 不支持循环依赖
    • 如果存在循环依赖,bean 加载就会一直递归下去直到堆栈溢出,所以Spring不支持原型bean循环依赖
  • depends-on 指定的前置依赖 bean,不能存在循环依赖,否则也会出现递归加载 bean 的情况,因为这时 bean 还未实例化,无法利用 earlyReference 机制

bean 加载过程中回调的一些 bpp 钩子函数(按调用顺序排序)

  • InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
    • bean 前置实例化处理,用于代替 Spring 直接加载 bean,返回被代理的 bean
  • MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
    • 修改 rootBeanDefinition,bean 实例化完成后执行
  • SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
    • 指定单例 bean 暴露的 earlyReference,否则就是 bean 实例自身。bean 实例化完成后执行
  • InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
    • bean 后置实例化处理,可用于填充 bean 属性,返回 false 则跳过 Spring 依赖注入和其他 bpp 的填充属性阶段
  • InstantiationAwareBeanPostProcessor#postProcessPropertyValues
    • 修改存储在 beanDefinition 的 property 标签声明的属性,pvs 里的属性值 set 给 bean 前执行
    • AutowiredAnnotationBeanPostProcessor是一个InstantiationAwareBeanPostProcessor,postProcessPropertyValues 方法里实现@Autowired 和@Value 的依赖注入
  • BeanPostProcessor#postProcessBeforeInitialization
    • bean 前置初始化处理,可以返回代理 bean
  • BeanPostProcessor#postProcessAfterInitialization
    • bean 后置初始化处理,可以返回代理 bean

bean 加载

加载前

尝试从单例缓存获取

从单例缓存或 earlyReference 缓存获取单例 bean

  • 优先取单例(一级)缓存,如果单例 bean 加载完成这里就直接取出来用,保障单例全局唯一
  • 如果单例缓存没有,从二级缓存拿 earlyReference,拿到了也直接用,作为依赖注入,解决循环依赖问题
  • 如果二级缓存也没有,从三级缓存拿到 earlyReference 的工厂类,调用工厂方法得到 earlyReference,再放到二级缓存
    • 三级缓存如果也没有,说明 bean 还没被实例化,因此无法从缓存直接获取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
// 缓存中不存在且单例在创建中,说明单例存在循环依赖
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 解决单例模式下的循环依赖,还在实例化过程中的单例,先放到earlySingletonObjects缓存
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}

FactoryBean

如果从缓存拿到 bean,会接着调用 getObjectForBeanInstance 拿到真正的 bean,这里主要是为了 FactoryBean 服务。如果三级缓存拿到的 bean 不是 FactoryBean 类型,就直接返回了

先说 FactoryBean 的加载流程。applicationContext 初始化阶段加载单例 bean 时,会从 bd 拿到 beanClass 判断类型,如果是 FactoryBean,getBean 传入的 beanName 前面要加上“&”,以保证确实想要加载 FactoryBean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}

FactoryBean 的加载流程其实和普通 bean 没区别,也要经历实例化-三级缓存-依赖注入-初始化这几个阶段,以及不同阶段的 bpp 钩子回调。getBean 传入的&,在 bean 加载阶段会干掉
加载完得到 FactoryBean 实例,返回前还要调用 getObjectForBeanInstance 方法,它的逻辑是这样:

  • 如果不是 FactoryBean 类型就返回了
  • 如果是
    • 传入的 beanName 以“&”开头,也直接返回 FactoryBean 实例
    • 不以“&”开头,调用 getObject 方法拿到 realBean 并缓存在 bf 的 factoryBeanObjectCache

所以,applicationContext 在 getBean 时传入了“&”,确保返回的就是 FactoryBean 实例。这时和 realBean 一点关系都没有。不过如果 FactoryBean 是 SmartFactoryBean,且 eagerInit 方法返回 true,会调用 getBean 方法传入 FactoryBean 的 beanName,注意此时没有“&”。先从三级缓存先拿到 FactoryBean 实例,然后调用 getObjectForBeanInstance 方法,根据上面的逻辑,会调用 getObject 方法得到 realBean,然后执行 bpp 的 postProcessAfterInitialization 后置初始化回调,最后缓存在 factoryBeanObjectCache,key=FactoryBean 的 beanName,value 为 realBean 实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 缓存不存在,调用工厂方法获取bean实例
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
// 尽可能保证所有bean初始化后都调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}

到这里你会发现,FactoryBean 和普通 bean 的加载流程并无差异。只是如果你想通过 getBean 拿到 FactoryBean 实例,需要加“&”,否则拿到的是 realBean。
realBean 和普通的 bean 完全不同,不会放在三级缓存里,且只有通过 getBean 方法传入 factoryBean 的 beanName 才能拿到,首次获取调用 getObject 并缓存在 bf 的 factoryBeanObjectCache

当我们将 realBean 按 byType 注入到其他 bean,在依赖注入阶段,Spring 会根据 realBean 的类型到 BeanDefinition 里匹配类型,如果是 FactoryBean 类型,匹配的是 getObject 返回的 realBean 类型。所以最后会匹配上 FacotoryBean,然后调用 getBean 方法传入 FactoryBean 的 beanName,这时拿到的就是 realBean 并注入

  • 测试代码:instantiation.before.factorybean.FactoryBeanTest#factoryBeanTest

循环依赖异常检测

原型 bean 循环依赖检测

如果是原型 bean,加载过程中发生重复加载,说明存在循环依赖,这会导致堆栈溢出,因此需要直接抛异常

1
2
3
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

depends-on 循环依赖检测

检测和 depends-on 前置依赖 bean 是否存在循环依赖

  • 存在循环依赖抛异常。因为 bean 还没被实例化,不能依赖 earlyReference 机制来解决循环依赖问题,先加载前置依赖的 bean 又会回过头来加载自己,导致无限递归堆栈溢出
  • 不存在则先加载前置依赖 bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 前置依赖的bean也依赖自己,产生循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 建立产生依赖的bean和被依赖的bean之间的关联关系,维护在bean工厂
registerDependentBean(dep, beanName);
try {
// 加载前置依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

单例 bean 循环依赖检测

spring 解决循环依赖是通过三级缓存和 earlyReference 机制,如果三级缓存拿不到 bean,且singletonsCurrentlyInCreation中包含该 beanName(说明 bean 正在加载中),证明 bean 存在无法通过 earlyReference 解决的循环依赖,直接抛异常,否则会导致递归加载 bean 直到堆栈溢出

  • 这种情况一般是构造器依赖产生的循环依赖,此时 bean 还没实例化,自然不在 earlyReference 缓存
1
2
3
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

bean 实例化

Spring 实例化 bean 分为三种情况

  • bpp 实例化前置处理直接实例化 bean
  • 使用指定的 factory-method 方法反射实例化
  • 使用构造函数反射实例化

bean 实例化前置处理

如果存在InstantiationAwareBeanPostProcessor,回调 postProcessBeforeInstantiation 方法执行实例化前置处理,直接获取 bean 实例,如果不为空,再调用 bpp 后置初始化处理,最后放入单例缓存,不参与其他的加载流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// bean实例化前置处理
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 如果bean实例化前置处理返回了bean实例,则调用bean初始化后置处理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// 标记bean是否在实例化前置处理中生成
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

determineTargetType 方法会确保拿到正确的 bean 类型,对于普通 bean,类型就是他自己,但如果是 factory-method 方式配置的 bean,类型是 factory-method 方法的返回类型

实例化 factory-method 方式配置的 bean

1
2
3
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

factory-method 方式的 bean 配置分为两种

  • xml 配置方式显式指定工厂类和工厂方法
    • bd.beanClass=工厂类 class,bd.factoryMethodName=配置指定的方法名,bd.factoryBeanName=null
    • 从 bd.beanClass 拿到工厂类,反射获取与 factoryMethodName 匹配的方法,然后反射调用该方法得到 bean 实例
    • 注意,这种方式工厂类不会作为 bean
  • @Bean 注解方式
    • bd.factoryBeanName=工厂类,bd.factoryMethodName=@Bean 修饰的方法名,bd.beanClass=null
    • 拿到 factoryBeanName 加载工厂 bean,拿到工厂 bean 的 class,反射获取与 factoryMethodName 匹配的方法,然后反射调用该方法得到 bean 实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
factoryClass = factoryBean.getClass();
isStatic = false;
}
else {
// It's a static factory method on the bean class.
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
// xml的factory-method配置方式,从beanClass里反射生成factory,调用工厂方法得到bean实例
factoryClass = mbd.getBeanClass();
isStatic = true;
}

测试代码:instantiation.ing.factorymethod.FactoryMethodTest

调用构造函数实例化 bean

如果 bean 没有指定 factory-method,则反射调用构造函数实例化 bean。选取构造函数有如下逻辑:

满足以下任意条件,使用有参构造函数实例化(构造函数的匹配规则没细看)

  • xml 配置了构造参数
  • 加载 bean 时传入了构造参数
  • SmartInstantiationAwareBeanPostProcessor指定了候选构造函数集
  • xml 配置的 autowireMode=AUTOWIRE_CONSTRUCTOR

注意,有参构造函数实例化前,会先加载依赖 bean,以及解析 SPEL 表达式的值

否则使用无参构造函数

1
2
3
4
5
6
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
return instantiateBean(beanName, mbd);

BeanWrapper 包装 bean 实例

实例化后的 Bean 使用BeanWrapper包装,作用是支持编辑 bean 实例的 property 属性。
Spring 在创建 beanWrapper 后调用 registerCustomEditors 方法,内部回调 beanFactory 里注入的所有PropertyEditorRegistrar属性编辑注册器,将用户自定义的PropertyEditor属性编辑器注册到 beanWrapper。

  • BeanWrapper本身是一个PropertyEditorRegistry属性编辑器注册中心
  • beanFactory 可以持有多个PropertyEditorRegistrar注册器,每个 registrar 在注册方法里可以注册多个PropertyEditor给 BeanWrapper
  • PropertyEditor可以编辑 xml 配置里 property 标签指定的 bean 属性字面量,或者将字面量转换为 bean 的实际属性类型
  • 测试代码:populatebean.propertyeditor.PropertyEditorTest

PropertyEditorRegistrar 是通过 bfpp 机制注入到 beanFactory 的。我们可以注册一个 bfpp:CustomEditorConfigurer,将 PropertyEditorRegistrar 注入给这个 bfpp,由它再后置处理 beanFactory 时注入到 beanFactory

1
2
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
registerCustomEditors(bw);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected void registerCustomEditors(PropertyEditorRegistry registry) {
PropertyEditorRegistrySupport registrySupport =
(registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
if (registrySupport != null) {
registrySupport.useConfigValueEditors();
}
if (!this.propertyEditorRegistrars.isEmpty()) {
for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
try {
// 调用beanFactory的注册器propertyEditorRegistrars,注册PropertyEditor到BeanWrapper
registrar.registerCustomEditors(registry);
}
catch (BeanCreationException ex) {
...
throw ex;
}
}
}
if (!this.customEditors.isEmpty()) {
this.customEditors.forEach((requiredType, editorClass) ->
registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)));
}
}

bpp 处理 BD

回调MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition处理 beanDefinition

1
2
3
4
5
6
7
8
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);
}
}
}

暴露 earlyReference

提前暴露一个可获取单例 earlyReference 的工厂,放入三级缓存(singletonFactories),循环依赖时回调工厂方法拿到 earlyReference,放入二级缓存(earlySingletonObjects)

  • 一级缓存是 singletonObjects
  • earlyReference 的工厂方法里回调 bpp 的方法SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference,允许定制 earlyReference
  • 通过二级缓存能判断 bean 是否存在循环依赖。这也是为什么不直接缓存 earlyReference 的原因
1
2
3
4
5
6
7
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 工厂方法生成earlyReference,如果有SmartInstantiationAwareBeanPostProcessor,回调bpp得到earlyReference
// 这就是为啥用工厂来返回earlyReference而不是直接把bean放到earlySingleton缓存的原因
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
1
2
3
4
5
6
7
8
9
10
11
12
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
1
2
3
4
5
6
7
8
9
10
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}

bpp 后置实例化处理

回调InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation方法执行 bean 实例化后置处理,允许在 Spring 依赖注入前为 bean 属性赋值。返回 false 会跳过回调其他 bpp 实例化后置处理方法,也会跳过 bean 依赖注入阶段

1
2
3
4
5
6
7
8
9
10
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}

依赖注入

按 autowireMode 加载依赖 bean

根据 xml 里 bean 配置的autowiredMode,byType 或 byName 加载不在 property 标签声明的 bean,存储在一个汇总的 propertyValueMap 里。最后的注入就是基于这个汇总的 pvMap,之所以这么做,是不想让非 property 标签描述的属性存储到 bd.pv 中。即,bd 应该是对 bean 配置的最纯粹的描述。

  • 如果不给 bean 配置 autowiredMode,不在 property 标签声明的属性不会做依赖注入
  • byType 注入时,会筛选出所有类型匹配或是类型的子类或实现这个接口类型的 beans。如果超过一个候选 bean,选择@Primary注解修饰的 bean,否则抛出 NoUniqueBeanDefinitionException 异常
  • property 标签中声明的 bean,以RuntimeBeanReference类型存储在 beanDefinition.propertyValues 中,在属性赋值前也会加载 bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 返回没有用<property>声明的引用类型属性名
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
// beanFactory是否包含bean定义或者bean已经加载并缓存在beanFactory
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
}
}
}
1
2
3
4
5
6
7
8
9
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
... ...

Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
// 依赖的bean实例添加到属性
pvs.add(propertyName, autowiredArgument);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
... ...

// 按类型查找与之匹配的bean,如果依赖的bean已经加载完成,从BeanFactory里获取bean实例,否则只加载依赖的beanClass
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
... ...

// 如果按类型查找到超过一个可注入的bean,@Primary修饰的bean优先作为候选
// 不存在@Primary修饰的bean,则抛异常NoUniqueBeanDefinitionException
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(type, matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
... ...

// 说明依赖的bean还未加载完成,调用BeanFactory.getBean加载bean
// 循环依赖时,返回的是earlyBean
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
... ...

return result;
}

注解驱动的依赖注入

回调InstantiationAwareBeanPostProcessor.postProcessPropertyValues方法

  • 如果存在AutowiredAnnotationBeanPostProcessor,回调该 bpp,注入@Autowired 修饰的依赖 bean、注入@Value 修饰的实际值
    • 只有基于注解驱动的 Spring 容器,例如AnnotationConfigApplicationContext,才会在容器的初始化阶段将 AutowiredAnnotationBeanPostProcessor 的 BD 注册到 beanFactory,然后在容器的 refresh 阶段加载注册的 bpp,注入到 beanFactory。因此如果是 xml 驱动的 Spring 容器,不能支持@Autowired、@Value 方式的依赖注入
    • @Value 如果用占位符,使用bf.embeddedValueResolvers解析得到实际值,如果用 spel 表达式,使用bd.beanExpressionResolver解析得到实际值。Spring 容器会给 bf 添加这两个 resolver 的默认实现。如果解析占位符,有优先级,默认是 JVM 参数-环境变量-系统配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 回调`InstantiationAwareBeanPostProcessor.postProcessPropertyValues`方法修改beanDefinition.propertyValues
// 回调`AutowiredAnnotationBeanPostProcessor`,注入@Autowired的依赖、注入计算后的@Value表达式(SPEL、环境变量占位符)的值
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}

AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

// 寻找使用@Value注解或者@Autowired注解的属性
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 解析使用@Value注解或者@Autowired注解的属性值,并赋值给bean
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
... ...

ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 寻找使用@Value注解或者@Autowired注解的属性
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
}

private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
if (ao.getAnnotations().length > 0) { // autowiring annotations have to be local
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
if (attributes != null) {
return attributes;
}
}
}
return null;
}

public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
... ...
}

解析 bd.pv 中的 value

经过上面这些步骤,注解驱动的依赖都已经注入了,还没注入的都存储在汇总的 propertyValueMap 中(包括 bd.pv,即标签配置的依赖)。在注入给 bean 之前,还要对 map 里的 value 做最后解析

  • 1、如果 value 使用了 SPEL 表达式,计算得到结果
    • 使用注册到 beanFactory 的BeanExpressionResolver(ApplicationContext 在 refresh 初始化阶段会注册StandardBeanExpressionResolver)解析 SPEL 表达式
  • 2、byName 加载 property 标签中声明的依赖 bean
  • 3、使用与 bean 属性类型匹配的 BeanWrapper.PropertyEditor 对 property 标签的属性字面量编辑或转换为 bean 的实际属性类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// bean的依赖引用类型在beanDefinition.propertyValues里的属性类型是RuntimeBeanReference
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
// 如果依赖的属性是引用bean,byName从beanFactory获取bean
return resolveReference(argName, ref);
}
... ...

else if (value instanceof TypedStringValue) {
TypedStringValue typedStringValue = (TypedStringValue) value;
// 使用beanExpressionResolver解析xml配置的表达式字面量
// ApplicationContext给beanFactory注册的beanExpressionResolver是StandardBeanExpressionResolver,它内部使用SpelParser解析spel表达式
Object valueObject = evaluate(typedStringValue);
return valueObject;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue, @Nullable Object newValue,
@Nullable Class<T> requiredType, @Nullable TypeDescriptor typeDescriptor) throws IllegalArgumentException {
// Custom editor for this type?
// 寻找该类型的自定义属性编辑器
PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
... ...

if (editor != null && !(convertedValue instanceof String)) {
try {
editor.setValue(convertedValue);
Object newConvertedValue = editor.getValue();
if (newConvertedValue != convertedValue) {
convertedValue = newConvertedValue;
editor = null;
}
}
catch (Exception ex) {}
}
if (convertedValue instanceof String) {
if (editor != null) {
String newTextValue = (String) convertedValue;
return doConvertTextValue(oldValue, newTextValue, editor);
}
else if (String.class == requiredType) {
returnValue = convertedValue;
}
}
}
1
2
3
4
5
6
7
8
private Object doConvertTextValue(@Nullable Object oldValue, String newTextValue, PropertyEditor editor) {
try {
editor.setValue(oldValue);
}
catch (Exception ex) {}
editor.setAsText(newTextValue);
return editor.getValue();
}

执行注入

最后基于 汇总的 propertyValueMap,填充 bean 属性值

1
2
// 基于bd.pv,填充bean属性值
bw.setPropertyValues(new MutablePropertyValues(deepCopy));

bean 初始化

自省注入

bean 如果是自省的,回调 bean 的自省方法注入 Spring 组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}

bpp 初始化前置处理

回调BeanPostProcessor.postProcessBeforeInitialization执行 bean 初始化前置处理

1
2
3
4
5
6
7
8
9
10
11
12
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

回调 afterPropertiesSet

如果 bean 实现 InitializingBean 接口,调用 bean 的 afterPropertiesSet 方法

1
2
3
4
5
// 如果bean实现InitializingBean接口,调用bean的afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
((InitializingBean) bean).afterPropertiesSet();
}

回调 init

xml 配置或@Bean 方式指定了 bean 的 init 方法时回调

1
2
3
4
5
6
7
8
9
// 反射调用bean的init方法(init方法声明在bean的xml定义文件)
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}

bpp 初始化后置处理

回调BeanPostProcessor.postProcessAfterInitialization执行 bean 初始化后置处理

1
2
3
4
5
6
7
8
9
10
11
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

加载后

earlyReference 可靠性检测

当 bean 在 bpp 的前置/后置处理时被代理,且 bean 存在循环依赖(earlyReference 能拿到 bean),则其他 beans 注入的 earlyReference 已失效,即 Spring 为循环依赖提供的 earlyReference 机制失效,抛 BeanCurrentlyInCreationException 异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
if (earlySingletonExposure) {
// 查询singletonEarlyReference
Object earlySingletonReference = getSingleton(beanName, false);
// earlyReference不为空说明存在循环依赖
if (earlySingletonReference != null) {
// exposedObject == bean 说明bean未被bpps在初始化处理时代理
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// bean已被代理,与earlySingletonReference不一致,依赖该bean的其他beans拿到的并不是真正的bean
// allowRawInjectionDespiteWrapping=true表示允许这种情况,默认为false
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// 依赖当前bean的其他已加载的beans
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
// 筛除typeCheckOnly加载的dependentBeans
for (String dependentBean : dependentBeans) {
// org.springframework.beans.factory.support.AbstractBeanFactory.getBean(java.lang.String) 方法加载bean不是typeCheckOnly
// 所以如果依赖当前bean的其他beans是调用getBean加载的,就是actualDependentBeans了
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
// 有其他已加载的beans依赖当前bean,且当前bean已被代理,则抛异常
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}

支持 bean 销毁回调

bean 配置销毁回调有这些方式:

  • bean 实现 DisposableBean 接口
  • xml 里显示指定 destroy-method
  • @Bean 里显示指定 destroy-method
  • 存在 DestructionAwareBeanPostProcessor 支持 bean 的销毁回调
    • requiresDestruction 方法传入 bean,返回 true

Spring 会为配置销毁回调的单例 bean 创建对应的销毁适配器DisposableBeanAdapter,并缓存在 BeanFactory,key=beanName

1
2
3
4
5
6
7
8
9
10
11
12
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
... ...
}
}
}
1
2
3
4
5
   protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return (bean.getClass() != NullBean.class &&
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}
1
2
3
4
5
6
7
8
9
10
11
   public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true;
}
String destroyMethodName = beanDefinition.getDestroyMethodName();
if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName)) {
return (ClassUtils.hasMethod(bean.getClass(), CLOSE_METHOD_NAME) ||
ClassUtils.hasMethod(bean.getClass(), SHUTDOWN_METHOD_NAME));
}
return StringUtils.hasLength(destroyMethodName);
}

spring 容器调用 close 方法关闭时,会调用所有 DisposableBeanAdapter 的 destroy 方法执行 bean 的销毁流程:

  • 如果存在 DestructionAwareBeanPostProcessor 支持 bean 销毁,回调 bpp 的 bean 销毁前置回调方法
  • 如果 bean 实现了 DisposableBean 接口,回调 destroy 方法
  • 如果 bean 配置了 destroy-method,回调配置的 destroy-method 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
   @Override
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}

if (this.invokeDisposableBean) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}

if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod(this.destroyMethodName);
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}

缓存单例 bean

1
2
3
4
5
6
7
8
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}

总结