5

系统学习Spring源码-bean加载

 1 year ago
source link: https://dcbupt.github.io/2020/04/23/blog_article/%E7%B3%BB%E7%BB%9F%E5%AD%A6%E4%B9%A0%E7%B3%BB%E5%88%97/%E7%B3%BB%E7%BB%9F%E5%AD%A6%E4%B9%A0Spring%E6%BA%90%E7%A0%81-bean%E5%8A%A0%E8%BD%BD/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

系统学习Spring源码-bean加载

2020-04-232023-06-10系统学习系列

Counter not initialized! More info at console err msg.℃ 8.6k 14 分钟

系统学习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 还没被实例化,因此无法从缓存直接获取
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

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 实例

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,加载过程中发生重复加载,说明存在循环依赖,这会导致堆栈溢出,因此需要直接抛异常

if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

depends-on 循环依赖检测

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

  • 存在循环依赖抛异常。因为 bean 还没被实例化,不能依赖 earlyReference 机制来解决循环依赖问题,先加载前置依赖的 bean 又会回过头来加载自己,导致无限递归堆栈溢出
  • 不存在则先加载前置依赖 bean
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 缓存
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 后置初始化处理,最后放入单例缓存,不参与其他的加载流程

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

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 实例
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 表达式的值

否则使用无参构造函数

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

BeanWrapper bw = new BeanWrapperImpl(beanInstance);
registerCustomEditors(bw);
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

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 的原因
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 工厂方法生成earlyReference,如果有SmartInstantiationAwareBeanPostProcessor,回调bpp得到earlyReference
// 这就是为啥用工厂来返回earlyReference而不是直接把bean放到earlySingleton缓存的原因
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
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;
}
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 依赖注入阶段

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
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;
}
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);
}
}
}
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);
}
}
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 参数-环境变量-系统配置文件
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

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;
}
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 的实际属性类型
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;
}
}
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;
}
}
}
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 属性值

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

bean 初始化

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

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 初始化前置处理

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 方法

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

回调 init

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

// 反射调用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 初始化后置处理

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 异常

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

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 {
... ...
}
}
}
   protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return (bean.getClass() != NullBean.class &&
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}
   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 方法
   @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

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);
}
}

bean%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B.png


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK