当前位置:   article > 正文

Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存_spring缓存

spring缓存

导航:

【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析

目录

一、概念准备 

1.1 循环依赖

1.2 Bean的生命周期

二、环境准备

2.1 代码准备

2.2 如何给Spring源码添加注释?

2.2.1 方法一:IDEA插件Private Notes

2.2.2 方法二(推荐):覆盖类(基于双亲委派模型)

三、三级缓存介绍

3.1 简介

3.2 源码位置:DefaultSingletonBeanRegistry类

3.3 详解ObjectFactory

3.3.1 函数式接口回顾

3.3.2 ObjectFactory

四、三级缓存解决循环依赖

4.0 核心流程简化版

4.1 前置流程

4.1.1 方法调用链:getBean() -> doGetBean() -> getSingleton() -> createBean() -> doCreateBean()

4.1.2 详解doCreateBean()方法

4.2 推断并实例化Bean

4.2.1 核心流程 

4.2.2 详解createBeanInstance():推断构造方法并实例化Bean

4.3 存入第三级缓存 

4.3.1 概述 

4.3.2 addSingletonFactory():存入第三级缓存

4.3.3 getEarlyBeanReference():生成提前代理对象

4.4 属性填充:解决循环依赖在这一步完成

4.4.1 概述

4.4.2 populateBean():属性填充

4.4.3 applyPropertyValues():解析、转换所有属性

4.4.4 resolveValueIfNecessary():根据类型解析属性

4.4.4.1 基本介绍

4.4.4.2 BeanDefinitionValueResolver类: 解析Bean的属性

4.4.5 resolveReference():调用getBean()解析属性为Bean

4.4.6 属性获取Bean流程:getBean() -> doGetBean()

4.4.6.1 直接从缓存中获取到AService

4.4.6.2 getSingleton(beanName) :从缓存中获取单例Bean

4.4.6.3 getSingleton(beanName,true):从缓存中获取单例Bean(是否允许循环依赖)

4.4.6.4 回顾doGetBean():getBean()的核心逻辑处理方法

4.5 doCreateBean的其他逻辑


一、概念准备 

1.1 循环依赖

Spring循环依赖:在Spring应用程序中两个或多个Bean彼此之间存在直接或间接的依赖关系,并且这种依赖关系形成了一个循环。

简而言之,循环依赖就是Bean A注入了Bean B,同时Bean B注入了Bean A,那么这两个Bean就形成了一个依赖关系。

举例:

举个例子,以下代码中,AService和BService就形成了一个循环依赖关系:

AService注入BService: 

  1. /**
  2. * @Author: vince
  3. * @CreateTime: 2024/03/15
  4. * @Description: AService
  5. * @Version: 1.0
  6. */
  7. @Component
  8. public class AService {
  9. /**
  10. * 注入BService
  11. */
  12. @Resource
  13. private BService bService;
  14. }

 BService注入AService:

  1. /**
  2. * @Author: vince
  3. * @CreateTime: 2024/03/15
  4. * @Description: BService
  5. * @Version: 1.0
  6. */
  7. @Component
  8. public class BService {
  9. /**
  10. * 注入AService
  11. */
  12. @Resource
  13. private AService aService;
  14. }

1.2 Bean的生命周期

源码解析:

Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程-CSDN博客

Bean的生命周期:指从Bean的创建到销毁的整个过程,主要包括Bean的创建、初始化、使用和销毁等阶段。

生命周期的详细阶段: 

1.扫描Bean:Spring启动后,基于反射通过@ComponentScan、@Component等注解找到所有Bean,并给每个Bean创建BeanDefinition对象(存放Class对象、作用域等信息),放进beanDefinitionMap(映射关系是"Bean名"--->“对应的BeanDefinition”。);

2.遍历beanDefinitionMap:遍历所有Bean进行Bean的创建,每个Bean的创建过程如下:

  • 推断构造方法、实例化:基于反射获取推断出的构造器对象,通过这个Constructor对象的newInstance(xx) 方法实例化类,得到原始对象;
  • 存入三级缓存:基于原始对象生成Lambda表达式,并放入三级缓存singletonFactories。以后如果执行这个Lambda表达式,生成的将是代理对象。
  • 属性填充:因为我们是从前到后遍历Bean的,所以存在当前Bean注入的属性Bean在加载时还没经历过声明周期得情况,那么这个属性Bean就要经历一次Bean的生命周期。具体的步骤如下:
    • 单例池找:先去一级缓存(单例池)找该Bean,若找到,则代表它已经历完整生命周期,没有发生循环依赖。一级缓存中存的是完整生命周期的Bean。
    • 判断循环依赖:若没找到,就代表它还未经过完整生命周期,要判断循环依赖。判断方法是在creattingSet<>中寻找该Bean,若找到则说明AService正在创建中,发生了循环依赖。
    • 二级缓存找:从二级缓存中找该Bean。二级缓存是earlySingletonObjects,存的就是未经历完整生命周期、提前aop的Bean。
    • 三级缓存找到,生成提前代理对象、存二级缓存:若没找到,就执行三级缓存该Bean的Lambda表达式,生成该Bean的提前代理对象,将其存入二级缓存并返回;
  • 处理Aware回调:如果Bean实例实现了BeanNameAware接口(通过instanceof判断),调用Bean重写的setBeanName()方法,给Bean实例的beanName变量赋值。
  • 执行所有BeanPostProcessor的初始化前方法:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessBeforeInitialization()方法。本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。
  • 初始化:如果Bean实例实现了InitializingBean接口(通过instanceof判断),调用Bean重写的afterPropertiesSet()方法,处理初始化逻辑。afterPropertiesSet译为“在属性填充之后”
  • 执行所有BeanPostProcessor的初始化后方法:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessAfterInitialization()方法。本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。
  • 存入单例池:如果是单例,就将最终的代理对象存入单例池(一级缓存,singletonObjects)。
  • 生存期:Bean已就绪,可以被使用,所有Bean将一直驻留在应用上下文中,直到应用上下文被销毁。
  • 销毁:如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果有方法注解了@PreDestroy,该方法也会被调用。

二、环境准备

2.1 代码准备

准备循环依赖所需的代码:

 AService注入BService: 

  1. /**
  2. * @Author: vince
  3. * @CreateTime: 2024/03/15
  4. * @Description: AService
  5. * @Version: 1.0
  6. */
  7. @Component
  8. public class AService {
  9. /**
  10. * 注入BService
  11. */
  12. @Resource
  13. private BService bService;
  14. }

 BService注入AService:

  1. /**
  2. * @Author: vince
  3. * @CreateTime: 2024/03/15
  4. * @Description: BService
  5. * @Version: 1.0
  6. */
  7. @Component
  8. public class BService {
  9. /**
  10. * 注入AService
  11. */
  12. @Resource
  13. private AService aService;
  14. }

测试类获取Bean

  1. /**
  2. * @Author: vince
  3. * @CreateTime: 2024/03/20
  4. * @Description: 测试类:循环依赖
  5. * @Version: 1.0
  6. */
  7. public class Test {
  8. public static void main(String[] args) {
  9. // 1.获取Spring容器,加载配置类
  10. ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  11. // 2.从容器中获取AService对象
  12. AService aService = context.getBean("AService", AService.class);
  13. }
  14. }

2.2 如何给Spring源码添加注释?

当我们进行debug时候,想要给Spring源码加注释,而源码都在项目引的依赖的jar包里,无法直接加注释,这就需要采取以下两种方法。

2.2.1 方法一:IDEA插件Private Notes

Private Notes 官方介绍:

你还在为项目中不敢添加 "敏感注释"! 源码是只读文件不能添加注释而烦恼吗? 

  • 在任何你想加注释的地方 按下Alt + Enter鼠标移出点击即可保存
  • 已有私人注释 按下Alt + Enter即可快速编辑
  • Alt + p 可快速添加或者编辑私人注释
  • Alt + o 展示私人注释的其它操作
  • 右键菜单私人注释查看操作

同步操作:

  • 数据都缓存当前用户目录下的 .privateNotes文件夹中,如需同步,可以借助强大的Git
  • 右键私人注释 可使用常用Git命令

安装步骤:

使用IDEA,搜索插件Private Notes并安装,然后重启即可生效:


 

使用效果:

打开任意源码,例如org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory,在任意行 “Alt + 回车”或者“Alt + P”,即可添加注释:

关闭注释窗口,可以看到效果:

2.2.2 方法二(推荐):覆盖类(基于双亲委派模型)

类加载机制和双亲委派模型:

Java的类是怎样在虚拟机中加载的?详细阐述JVM的加载、验证和解析过程-CSDN博客

双亲委派模型这里不再过多赘述,详情看上面文章。

基于双亲委派模型,我们可以在本地创建一个与原始类路径、全限定名完全一致的类,就可以实现对原类的覆盖,代码debug时,也会进入我们覆盖的类,而不是原类:

例如我们覆盖AbstractAutowireCapableBeanFactory类,代码内容也完全拷贝过来,仅修改doCreateBean()方法,加上断点,debug可以发现断点进了我们覆盖的类:

三、三级缓存介绍

Spring通过三级缓存解决了循环依赖问题。

3.1 简介

三级缓存: 

在Spring Bean的生命周期中,"三级缓存"用于解决循环依赖问题。当Spring容器创建Bean时,会将Bean的实例放置到三级缓存中,以确保在解决循环依赖问题时能够正确地获取已经创建的Bean实例。

  • singletonObjects(单例池):缓存的是已经经历了完整生命周期的bean对象。
  • earlySingletonObjects:缓存未经过完整生命周期的bean,也就是提前代理对象。用于循环依赖时,直接从二级缓存找提前代理对象。
  • singletonFactories:缓存的是一个Lambda表达式,参数包括原始对象,执行结果是提前代理对象。在Bean实例化后立刻存Lambda表达式到三级缓存里。发生循环依赖且二级缓存找不到提前代理对象时,会获取并执行Lambda表达式,将生成的提前代理对象先存入二级缓存再填充属性。

3.2 源码位置:DefaultSingletonBeanRegistry类

三级缓存在DefaultSingletonBeanRegistry类中声明,格式是三个Map:

  1. /**
  2. * 一级缓存,value是经过完整生命周期的Bean
  3. */
  4. private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  5. /**
  6. * 二级缓存,value是提前代理对象
  7. */
  8. private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
  9. /**
  10. * 三级缓存,value是Lambda表达式(ObjectFactory是一个函数式接口)
  11. * 函数式接口可以把匿名内部类、lambda表达式作为参数传递到方法中
  12. */
  13. private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

DefaultSingletonBeanRegistry类:负责注册、获取、缓存、销毁单例 bean。

核心方法:

  • 注册单例 bean:在容器启动时,将单例 bean 注册到注册表中。
    • registerSingleton(String beanName, Object singletonObject):将给定的单例对象注册到单例 bean 注册表中。
  • 获取单例 bean:根据 bean 的名称从注册表中获取对应的单例 bean 实例。
    • getSingleton(String beanName):根据给定的 bean 名称从注册表中获取对应的单例 bean 实例。
  • 缓存单例 bean:在首次获取单例 bean 后,将其缓存以供后续使用,避免重复创建。
    • containsSingleton(String beanName):检查注册表中是否包含指定名称的单例 bean。
  • 销毁单例 bean:在容器关闭时,销毁注册表中所有单例 bean 实例。
    • destroySingletons():销毁注册表中所有单例 bean 的实例。

3.3 详解ObjectFactory

3.3.1 函数式接口回顾

函数式接口是Java 8的一个新特性。 

函数式接口:有且仅有一个抽象方法的接口。实际使用时,函数式接口是方法的形参,实参是Lambda表达式。

注解:@FunctionalInterface

示例:java.util包下的生产者接口Supplier

  1. package java.util.function;
  2. /**
  3. * Represents a supplier of results.
  4. */
  5. @FunctionalInterface
  6. public interface Supplier<T> {
  7. /**
  8. * Gets a result.
  9. *
  10. * @return a result
  11. */
  12. T get();
  13. }

应用案例:使用Supplier,获取数组中的最大值:

  1. /**
  2. * @Author: vince
  3. * @CreateTime: 2024/03/20
  4. * @Description: 测试类
  5. * @Version: 1.0
  6. */
  7. public class Test {
  8. /**
  9. * 主方法
  10. * @param args 参数
  11. */
  12. public static void main(String[] args) {
  13. // 定义一个int数组
  14. int[] arr = {19, 50, 28, 37, 46};
  15. // 调用getMax方法,方法的形参是函数式接口(单方法接口),
  16. // 实参Lambda表达式(接口方法的逻辑,相当于创建了一个Supplier对象)
  17. // 返回值是Lambda表达式的返回值,sup.get()
  18. int maxValue = getMax(() -> {
  19. int max = arr[0];
  20. for (int i = 1; i < arr.length; i++) {
  21. if (arr[i] > max) {
  22. max = arr[i];
  23. }
  24. }
  25. return max;
  26. });
  27. System.out.println(maxValue);
  28. }
  29. /**
  30. * 返回一个int数组中的最大值,具体的逻辑由实参Lambda表达式决定
  31. * @param sup 供应商
  32. * @return int 最大值
  33. */
  34. private static int getMax(Supplier<Integer> sup) {
  35. return sup.get();
  36. }
  37. }

3.3.2 ObjectFactory

第三级缓存: 

首先我们看第三级缓存,它的value是ObjectFactory接口

  1. /**
  2. * 三级缓存,value是Lambda表达式(ObjectFactory是一个函数式接口)
  3. * 函数式接口可以把匿名内部类、lambda表达式作为参数传递到方法中
  4. */
  5. private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

什么是ObjectFactory?

ObjectFactory是一个函数式接口,因为它包含@FunctionalInterface注解。

它只有一个getObject()方法,用于获取实参Lambda表达式生成的Bean对象。

  1. @FunctionalInterface
  2. public interface ObjectFactory<T> {
  3. /**
  4. * Return an instance (possibly shared or independent)
  5. * of the object managed by this factory.
  6. * @return the resulting instance
  7. * @throws BeansException in case of creation errors
  8. */
  9. T getObject() throws BeansException;
  10. }

使用示例:

将获取存储进三级缓存:

函数式接口是一般都是形参,可以把匿名内部类、lambda表达式作为实参传递到方法中,例如下面语句是三级缓存实参示例:

singletonFactories.put("AService",()-> getEarlyBeanReference(beanName,mbd,AService);

这个语句中,实参“()-> getEarlyBeanReference(beanName,mbd,AService)”是一个Lambda表达式,它指定了ObjectFactory的getObject()方法的具体逻辑,是调用getEarlyBeanReference()方法。

以后如果根据Bean名从三级缓存Map中取出这个Lambda表达式(实际是ObjectFactory类型),调用它的get()方法,将执行aop并生成AService的代理对象。

四、三级缓存解决循环依赖

4.0 核心流程简化版

AService这个Bean的创建过程:

  1. 推断和实例化;
  2. 存入三级缓存;
  3. 属性填充BService,BService创建流程:
    1. 推断和实例化
    2. 存入三级缓存
    3. 属性填充AService
      1. 单例池找
      2. 判断循环依赖
      3. 二级缓存找
      4. 三级缓存找到,生成提前代理对象、存二级缓存
    4. 执行三级缓存
    5. 存入单例池
  4. AOP包裹初始化
  5. 存入单例池

解释: AService创建过程:

  • 推断和实例化:推断构造方法,实例化AService原始对象;
  • 存入三级缓存:生成Lambda表达式,并放入三级缓存。Lambda表达式参数包括原始对象,以后如果执行这个Lambda表达式,将执行aop并生成AService代理对象;singletonFactories.put('AService',()-> getEarlyBeanReference(beanName,mbd,AService普通对象)
  • 属性填充BService:去一级缓存、二级缓存找BService;如果没找到,则创建BService对象。BService创建流程:
    • 推断和实例化:推断构造方法和实例化BService原始对象;
    • 存入三级缓存:基于原始对象生成BService的Lambda表达式,并放入三级缓存。以后如果根据Bean名从三级缓存Map中取出这个Lambda表达式(实际是ObjectFactory类型),调用它的get()方法,将执行aop并生成AService的代理对象。
    • 属性填充AService:基于反射给AService属性填充AService代理对象;
      • 单例池找:先去一级缓存(单例池)找AService,若找到,则代表AService已经历完整生命周期,没有发生循环依赖。一级缓存中存的是完整生命周期的Bean。
      • 判断循环依赖:若没找到,就代表AService还未经过完整生命周期,要判断循环依赖。判断方法是在creattingSet<>中寻找AService,若找到则说明AService正在创建中,发生了循环依赖。
      • 二级缓存找:从二级缓存中找AService。二级缓存是earlySingletonObjects,存的就是未经历完整生命周期、提前aop的Bean。
      • 三级缓存找到,生成提前代理对象、存二级缓存:若没找到,就执行三级缓存AService的Lambda表达式,生成AService提前代理对象,将其存入二级缓存并返回;
    • 执行三级缓存:执行三级缓存BService的Lambda表达式,得到BService代理对象;
    • 存入单例池:BService代理对象放入一级缓存;
  • AOP包裹初始化:执行BeanPostProcessor的postProcessBeforeInitialization()方法;执行初始化方法:Bean重写InitializingBean接口的afterPropertiesSet();执行BeanPostProcessor的postProcessAfterInitialization()方法
  • 存入单例池:AService代理对象放入一级缓存;

4.1 前置流程

4.1.1 方法调用链:getBean() -> doGetBean() -> getSingleton() -> createBean() -> doCreateBean()

我们正常加载Spring容器,需要使用应用容器上下文加载配置类:

  1. /**
  2. * @Author: vince
  3. * @CreateTime: 2024/03/20
  4. * @Description: 测试类:循环依赖
  5. * @Version: 1.0
  6. */
  7. public class Test {
  8. public static void main(String[] args) {
  9. // 1.注解方式启动IOC容器,加载配置类
  10. ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  11. // 2.调用TestService的test()方法
  12. TestService testService = context.getBean(TestService.class, "testService");
  13. testService.test();
  14. }
  15. }

AnnotationConfigApplicationContext的构造方法会调用this.refresh();,它会调用finishBeanFactoryInitialization()方法初始化所有单例bean,然后调用preInstantiateSingletons()方法,它调用了getBean()。 

这个调用链此处不再累述,详细参考下文:

Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程-CSDN博客

这个getBean()方法将是Bean生命周期的主要方法。

getBean():

在Bean的生命周期中,主要有以下方法的调用:

  • getBean():
    • 作用:根据Bean名称获取Bean
    • 所属类:AbstractBeanFactory类:即抽象BeanFactory基类,它实现了BeanFactory接口,用于管理 BeanDefinition,并对Bean 进行创建、获取、销毁等操作。
    • 它调用了doGetBean()方法
  • doGetBean()方法:
    • 作用:getBean()的核心逻辑处理方法
    • 所属类:AbstractBeanFactory类:抽象BeanFactory基类。
    • 它调用了getSingleton()方法
  • getSingleton()方法:
    • 作用:获取单例Bean
    • 所属类:DefaultSingletonBeanRegistry类:用于注册、获取、缓存、销毁单例 bean
    • 它调用了createBean()方法
  • createBean()方法:
    • 作用:创建Bean
    • 所属类:AbstractAutowireCapableBeanFactory类:继承了AbstractBeanFactory类,提供了Bean初始化和依赖注入的实现。
    • 它调用了doCreateBean()方法
  • doCreateBean()方法:创建Bean的核心逻辑处理方法
    • 作用:创建Bean的核心逻辑处理方法
    • 所属类:AbstractAutowireCapableBeanFactory类:用于Bean初始化和依赖注入
    • 它调用了addSingletonFactory()方法,将刚创建的bean放入第三级缓存中(第三级缓存singleFactories(key是beanName,value是ObjectFactory))

4.1.2 详解doCreateBean()方法

具体参考下文的2.6小节, doCreateBean()方法:创建Bean的核心逻辑处理方法

Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程-CSDN博客

4.2 推断并实例化Bean

4.2.1 核心流程 

  1. 判断单例:创建一个BeanWrapper,如果是单例,则取出缓存赋值给它,并清除缓存
  2. wrapper为空时实例化Bean:调用createBeanInstance()方法,默认用无参构造方法实例化Bean,赋值给wrapper

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

 AbstractAutowireCapableBeanFactory是上面定义三级缓存的类DefaultSingletonBeanRegistry的子类,用于bean 初始化和自动装配(使用三级缓存解决了循环依赖),核心方法是autowireBean()、createBean()、doCreateBean()。

详见下文2.5.2:

Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程-CSDN博客

  1. // 1.判断单例:创建一个BeanWrapper,如果是单例,则取出缓存赋值给它,并清除缓存
  2. BeanWrapper instanceWrapper = null;
  3. // 如果BeanDefinition是单例模式,就先从缓存中清除
  4. if (mbd.isSingleton()) {
  5. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  6. }
  7. // 2.wrapper为空时实例化Bean:调用createBeanInstance()方法,默认用无参构造方法实例化Bean,赋值给wrapper
  8. // bean初始化第一步:默认调用无参构造实例化Bean
  9. // 构造参数依赖注入,就是发生在这一步
  10. if (instanceWrapper == null) {
  11. instanceWrapper = createBeanInstance(beanName, mbd, args);
  12. }

上面代码中核心代码是下面一行,调用调用createBeanInstance()方法,推断和实例化Bean:

4.2.2 详解createBeanInstance():推断构造方法并实例化Bean

上面doCreateBean()方法的第2步,如果从缓存中没取到BeanWrapper(Bean包装器,用于获取Bean实例、Class对象和属性),则执行createBeanInstance()创建Bean实例。

核心流程:

  • 解析获取 Bean 的Class对象:调用 resolveBeanClass(mbd, beanName)方法解析 Bean ,获取Bean 的Class对象,用于获取类的属性和调用newInstance()方法实例化。
  • 校验 Bean 必须非空且public:如果 Bean 类型为null、或者不是公共类,则抛出异常。
  • 判断是否使用Supplier创建 Bean:如果 BeanDefinition 中包含实例供应器Supplier(根据BeanDefiniton的instanceSupplier属性判断),则调用该实例供应器来创建 Bean 实例。
  • 判断是否使用工厂方法创建 Bean: BeanDefinition 中配置了工厂方法,则尝试调用该工厂方法来创建 Bean 实例。
  • 判断构造函数是否缓存过:如果已经解析过 Bean 类型的构造函数,并且不需要自动装配,则直接使用缓存的构造函数或默认构造函数来创建 Bean 实例。缓存位置在BeanDefinition 的resolvedConstructorOrFactoryMethod字段,缓存值的类型是Executable(代表可执行的程序单元,可以是普通方法或者构造方法,可以通过它获取方法的参数类型、个数等信息)
  • 判断构造函数是否需要自动装配:如果存在可选构造函数、设置了构造参数值、有参与构造函数参数列表的参数或者配置了构造函数自动装配,则进入自动装配构造函数的流程。
  • 后置处理器中寻找候选构造函数:从 Bean 的后置处理器中寻找候选构造函数,这些构造函数可能是通过 @Autowired 注解标注的构造函数或者是通过其他方式标注的。
  • 推断构造函数并自动装配:根据候选构造函数和参数来确定最终的构造函数,并进行自动装配。

详细流程:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory 

  1. /**
  2. * 根据BeanDefinition中的信息,创建Bean实例
  3. *
  4. * @param beanName Bean的名称
  5. * @param mbd Bean的定义信息
  6. * @param args 构造器参数
  7. * @return {@link BeanWrapper}
  8. */
  9. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
  10. // 1.获取Bean 的Class对象,用于获取类的属性和调用newInstance()方法实例化
  11. // 解析Bean的类型,确认需要创建的bean实例的类可以实例化。
  12. // 如果没有设置通过Class.forName获取Bean类型
  13. Class<?> beanClass = resolveBeanClass(mbd, beanName);
  14. // 2.校验 Bean 必须非空且public:如果 Bean 类型为null、或者不是公共类,则抛出异常。
  15. // 确保class不为空,并且访问权限是public
  16. if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
  17. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  18. "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
  19. }
  20. // 3.判断是否使用Supplier创建 Bean:如果 BeanDefinition 中包含实例供应器Supplier,则调用该实例供应器来创建 Bean 实例。
  21. // ①Supplier方式创建Bean: 需要先有回调Bean
  22. // 判断当前beanDefinition中是否包含实例供应器,此处相当于一个回调方法,利用回调方法来创建bean
  23. Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
  24. if (instanceSupplier != null) {
  25. return obtainFromSupplier(instanceSupplier, beanName);
  26. }
  27. // 4.判断是否使用工厂方法创建 Bean: BeanDefinition 中配置了工厂方法,则尝试调用该工厂方法来创建 Bean 实例。
  28. // ②FactoryMethod方式创建Bean: 需要在XML中配置factory-method
  29. // 判断是否有工厂方法,如果存在,会尝试调用该Bean定义信息中的工厂方法来获取实例
  30. if (mbd.getFactoryMethodName() != null) {
  31. return instantiateUsingFactoryMethod(beanName, mbd, args);
  32. }
  33. // 5.判断构造函数是否缓存过:
  34. // 如果已经解析过 Bean 类型的构造函数,并且不需要自动装配,则直接使用缓存的构造函数或默认构造函数来创建 Bean 实例。
  35. // 缓存位置在BeanDefinition 的resolvedConstructorOrFactoryMethod字段;
  36. // 缓存值的类型是Executable(代表可执行的程序单元,可以是普通方法或者构造方法,可以通过它获取方法的参数类型、个数等信息)
  37. // Shortcut when re-creating the same bean...
  38. //一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器,当多次构建同一个 bean 时就不需要重新判断应该使用那种方式构造Bean
  39. boolean resolved = false;
  40. //是否需要自动装配
  41. boolean autowireNecessary = false;
  42. if (args == null) {
  43. synchronized (mbd.constructorArgumentLock) {
  44. // 因为判断过程会比较慢,所以spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod字段中。
  45. // 在下次创建相同时直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值获取,避免再次解析,导致循环依赖
  46. // 这个字段是一个包可见的字段,用于缓存已解析的构造函数或工厂方法。
  47. if (mbd.resolvedConstructorOrFactoryMethod != null) {
  48. //标识以及解析过class的构造器
  49. resolved = true;
  50. autowireNecessary = mbd.constructorArgumentsResolved;
  51. }
  52. }
  53. }
  54. // 6.判断是否需要自动装配构造函数:如果存在可选构造函数、设置了构造参数值、有参与构造函数参数列表的参数或者配置了构造函数自动装配,则进入自动装配构造函数的流程。
  55. // 有构造参数的或者工厂
  56. if (resolved) {
  57. //已经解析过class的构造器,使用已经解析好的构造器
  58. if (autowireNecessary) {
  59. //构造函数自动注入
  60. return autowireConstructor(beanName, mbd, null, null);
  61. } else {
  62. //使用默认构造器
  63. return instantiateBean(beanName, mbd);
  64. }
  65. }
  66. // 7.后置处理器中寻找候选构造函数:从 Bean 的后置处理器中寻找候选构造函数,这些构造函数可能是通过 @Autowired 注解标注的构造函数或者是通过其他方式标注的。
  67. Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  68. // 8.推断构造函数并自动装配:根据候选构造函数和参数来确定最终的构造函数,并进行自动装配。
  69. // 从bean后置处理器中为自动装配寻找构造方法
  70. // 以下情况符合其一即可进入
  71. // 1、存在可选构造方法
  72. // 2、自动装配模型为构造函数自动装配
  73. // 3、给BeanDefinition中设置了构造参数值
  74. // 4、有参与构造函数参数列表的参数
  75. if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
  76. mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  77. return autowireConstructor(beanName, mbd, ctors, args);
  78. }
  79. // Preferred constructors for default construction?
  80. // 从bean后置处理器中为自动装配寻找构造方法, 有且仅有一个有参构造或者有且仅有@Autowired注解构造
  81. ctors = mbd.getPreferredConstructors();
  82. if (ctors != null) {
  83. // 构造函数自动注入
  84. // 二、有参构造创建Bean
  85. return autowireConstructor(beanName, mbd, ctors, null);
  86. }
  87. // No special handling: simply use no-arg constructor.
  88. // 使用默认无参构造函数创建对象,如果没有无参构造且存在多个有参构造且没有@AutoWired注解构造,会报错
  89. //三、无参构造创建Bean
  90. return instantiateBean(beanName, mbd);
  91. }

4.3 存入第三级缓存 

4.3.1 概述 

在上面doCreateBean()的第四步——"依赖处理"阶段,调用了下面这一行代码,将实例化后的Bean存入三级缓存,key是beanName,value是ObjectFactory(形参是这个函数式接口,实参是Lambda表达式):

  1. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

实参“()-> getEarlyBeanReference(beanName,mbd,AService)”是一个Lambda表达式,它指定了ObjectFactory的getObject()方法的具体逻辑,是调用getEarlyBeanReference()方法。

以后如果根据Bean名从三级缓存Map中取出这个Lambda表达式(实际是ObjectFactory类型),调用它的get()方法,将执行aop并生成AService的代理对象。

4.3.2 addSingletonFactory():存入第三级缓存

核心逻辑:

  • 存入三级缓存:如果一级缓存里没有该Bean,就放入三级缓存、移除二级缓存、添加到已注册Bean集合;如果一级缓存有该Bean,就代表这个Bean被加载过,无需操作

具体代码: 

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry 
  1. /**
  2. * 为指定的 bean 名称的Bean,添加到第三级缓存。
  3. *
  4. * @param beanName bean 的名称
  5. * @param singletonFactory bean 的单例工厂
  6. * @throws IllegalArgumentException 如果单例工厂为 {@code null}
  7. */
  8. protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
  9. Assert.notNull(singletonFactory, "Singleton factory must not be null");
  10. synchronized (this.singletonObjects) {
  11. // 1.如果一级缓存里没有这个Bean,就放入三级缓存、移除二级缓存;如果有就代表这个Bean被加载过,无需操作
  12. if (!this.singletonObjects.containsKey(beanName)) {
  13. // 放入三级缓存
  14. this.singletonFactories.put(beanName, singletonFactory);
  15. // 从二级缓存移除
  16. this.earlySingletonObjects.remove(beanName);
  17. // 添加到已注册单例的集合中
  18. this.registeredSingletons.add(beanName);
  19. }
  20. }
  21. }

4.3.3 getEarlyBeanReference():生成提前代理对象

核心逻辑:

  • 生成提前代理对象:执行Lambda表达式,遍历所有后置处理器BeanPostProcessor,生产提前代理对象。因为这个对象还不是经历完整生命周期的Bean,还没有被IOC容器管理,只是用于解决循环依赖问题,所以称他为“提前代理对象”。

具体代码:  

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory 

  1. /**
  2. * 获取指定 bean 的提前代理对象,通常用于解决循环引用的目的。
  3. *
  4. * @param beanName bean 的名称(用于错误处理目的)
  5. * @param mbd bean 的合并后的 BeanDefinition
  6. * @param bean 原始的 bean 实例
  7. * @return 要暴露为 bean 引用的对象
  8. */
  9. protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
  10. // 默认情况下,暴露对象(即提前代理对象)为原始的 bean 实例
  11. Object exposedObject = bean;
  12. // 遍历所有后置处理器BeanPostProcessor,增强暴露对象
  13. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  14. // 遍历所有 BeanPostProcessor
  15. for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
  16. exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
  17. }
  18. }
  19. return exposedObject;
  20. }

4.4 属性填充:解决循环依赖在这一步完成

4.4.1 概述

Bean创建过程的核心方法doCreateBean(),第5步是依赖填充,将当前Bean注入的各个包含@Value,@Autowired,@Resource等注解的属性进行填充,这些注入的Bean可能还没有初始化,也可能初始化过并且它们的属性也包含当前Bean,这就产生了循环依赖,这个步骤使用三级缓存解决了循环依赖。

  1. // 5.填充属性(DI依赖注入发生在此步骤)
  2. // 对bean进行填充,将各个属性值注入,其中可能存在依赖于其他bean的属性,会递归初始化
  3. populateBean(beanName, mbd, instanceWrapper);

4.4.2 populateBean():属性填充

核心流程:

  1. 执行所有后置处理器(实例化后):判断当前Bean是否实现了后置处理器InstantiationAwareBeanPostProcessor接口,如果实现了,则执行postProcessPropertyValues()方法,这个方法专门在Bean的属性注入之前调用;
  2. 自动装配:判断根据名称注入,还是按类型自动注入,然后调用autowireByName()或autowireByType()注入;
  3. 依赖检查:如果依赖注入后的属性值为空,并且没有过滤需要进行依赖检查的 PropertyDescriptor 集合,则过滤并检查;
  4. 将属性应用到bean中:对属性值解析和转换,确保属性值能够正确地应用到 Bean 实例中;

  1. /**
  2. * 属性填充方法,给定一个bean名称,根Bean定义和Bean包装器,为Bean设置属性值。
  3. *
  4. * @param beanName bean的名称
  5. * @param mbd bean的根Bean定义
  6. * @param bw bean的Bean包装器
  7. */
  8. protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
  9. // 空值校验
  10. if (bw == null) {
  11. if (mbd.hasPropertyValues()) {
  12. throw new BeanCreationException(
  13. mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
  14. }
  15. else {
  16. // Skip property population phase for null instance.
  17. return;
  18. }
  19. }
  20. /**
  21. * 1.执行属性注入前后置处理器
  22. * 这里调用了 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation方法
  23. * 给InstantiationAwareBeanPostProcessor最后一次机会在属性设置前来改变bean
  24. * 注意:如果实现这个类并且在postProcessAfterInstantiation()返回 false 可以导致其他实例无法注入
  25. */
  26. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  27. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  28. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  29. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  30. if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
  31. return;
  32. }
  33. }
  34. }
  35. }
  36. PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
  37. int resolvedAutowireMode = mbd.getResolvedAutowireMode();
  38. // 2.按名或类型自动装配:
  39. // 根据名称或类型自动注入,从Spring2.5开始,开始支持使用注解(@Autowired)来自动装配Bean的属性
  40. if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
  41. MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
  42. // Add property values based on autowire by name if applicable.
  43. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
  44. // 名称注入
  45. autowireByName(beanName, mbd, bw, newPvs);
  46. }
  47. // Add property values based on autowire by type if applicable.
  48. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
  49. // 类型注入
  50. autowireByType(beanName, mbd, bw, newPvs);
  51. }
  52. pvs = newPvs;
  53. }
  54. boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
  55. // 3.依赖检查
  56. boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
  57. PropertyDescriptor[] filteredPds = null;
  58. if (hasInstAwareBpps) {
  59. if (pvs == null) {
  60. pvs = mbd.getPropertyValues();
  61. }
  62. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  63. // 对于每一个后置处理器,如果是 InstantiationAwareBeanPostProcessor 的实现类,则调用其 postProcessProperties 方法来进行依赖注入过程。
  64. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  65. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  66. // 依赖注入过程
  67. PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
  68. if (pvsToUse == null) {
  69. if (filteredPds == null) {
  70. // 过滤出需要进行依赖检查的PropertyDescriptor集合,用于:
  71. // 1、若存在InstantiationAwareBeanPostProcessor类型的后置处理器,
  72. // 则各属性调用postProcessPropertyValues 方法(在Bean的属性注入之前调用),这些属性是由上述的过滤方法过滤得到;
  73. // 2、后续检查需要设置值的属性是否已经初始化;作用也是用于筛选需要处理的属性,个人感觉这部分使用是扩展和辅助检查,更重要的是“第一处”中的使用。
  74. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  75. }
  76. // 老版本用这个方式去注入
  77. pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
  78. if (pvsToUse == null) {
  79. return;
  80. }
  81. }
  82. pvs = pvsToUse;
  83. }
  84. }
  85. }
  86. if (needsDepCheck) {
  87. if (filteredPds == null) {
  88. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  89. }
  90. // 依赖检查,对应 depends-on 属性,3.0 已弃用,这里不在分析
  91. checkDependencies(beanName, mbd, filteredPds, pvs);
  92. }
  93. if (pvs != null) {
  94. // 4.将属性应用到bean中:
  95. // 对属性值解析和转换,确保属性值能够正确地应用到 Bean 实例中;
  96. applyPropertyValues(beanName, mbd, bw, pvs);
  97. }
  98. }

4.4.3 applyPropertyValues():解析、转换所有属性

上面populateBean()方法第四步调用了 applyPropertyValues()方法,这个方法主要作用是将所有属性统一注册为Bean。它遍历所有属性并解析加到深拷贝列表,解析完所有属性后应用到bean。为了不影响到BeanDefinition的属性集合才使用深拷贝。

核心逻辑:

  1. 非空校验:如果属性值列表是空的,结束注入流程;
  2. 判断属性值列表的类型:将转换过的属性赋值到BeanWrapper的对应属性中,然后转为List集合,交给original;
  3. 遍历属性值列表:如果每个属性转换过则直接加入深拷贝列表中,如果没转换过则将属性解析、转换后加入deepCopy;
  4. 将解析后的属性值列表赋值给BeanWrapper:将解析后的深拷贝列表转为MutablePropertyValues类型后,set到BeanWrapper中;

具体代码:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory  

  1. /**
  2. * 将所有属性统一注册为Bean:遍历所有属性并解析加到深拷贝列表,解析完所有属性后应用到bean。
  3. * 将给定的属性值应用到 Bean 实例中,同时解析任何运行时引用到此 Bean 工厂中的其他 Bean。
  4. * 在这个过程中,必须进行深度拷贝,以避免永久修改属性。
  5. *
  6. * @param beanName Bean的名称
  7. * @param mbd Bean的定义信息
  8. * @param bw BeanWrapper对象
  9. * @param pvs 属性值列表
  10. */
  11. protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
  12. // 1.非空校验:如果属性值列表是空的,结束注入流程
  13. if (pvs.isEmpty()) {
  14. return;
  15. }
  16. if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
  17. ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
  18. }
  19. MutablePropertyValues mpvs = null;
  20. List<PropertyValue> original;
  21. // 2.判断属性值列表的类型:将转换过的属性赋值到BeanWrapper的对应属性中,然后转为List集合,交给original
  22. // 它可能是MutablePropertyValues类型的,也可能是PropertyValues类型的
  23. // 2.1 如果是MutablePropertyValues类型的,则将转换过的属性列表直接set到BeanWrapper中,然后将属性值列表转换为List集合
  24. // 2.2 如果不是,则将属性值列表转换为List集合
  25. if (pvs instanceof MutablePropertyValues) {
  26. mpvs = (MutablePropertyValues) pvs;
  27. // 如果属性值列表已经被转换过,将其直接set到BeanWrapper中
  28. if (mpvs.isConverted()) {
  29. // Shortcut: use the pre-converted values as-is.
  30. try {
  31. bw.setPropertyValues(mpvs);
  32. return;
  33. } catch (BeansException ex) {
  34. throw new BeanCreationException(
  35. mbd.getResourceDescription(), beanName, "Error setting property values", ex);
  36. }
  37. }
  38. original = mpvs.getPropertyValueList();
  39. } else {
  40. // 如果不是,则将属性值列表转换为List集合,交给original
  41. original = Arrays.asList(pvs.getPropertyValues());
  42. }
  43. // 获取自定义类型转换器
  44. TypeConverter converter = getCustomTypeConverter();
  45. if (converter == null) {
  46. converter = bw;
  47. }
  48. // 创建一个BeanDefinitionValueResolver对象
  49. // 用于解析属性值。该对象接收当前的 BeanDefinition 对象、bean 的名称、自定义的类型转换器作为参数
  50. BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
  51. // 创建一个深拷贝列表deepCopy,用于存储解析转换过的属性
  52. List<PropertyValue> deepCopy = new ArrayList<>(original.size());
  53. boolean resolveNecessary = false;
  54. // 3.遍历属性值列表:如果每个属性转换过则直接加入deepCopy中,如果没转换过则将属性解析、转换后加入deepCopy
  55. // 每一个属性值都是一个键值对
  56. for (PropertyValue pv : original) {
  57. if (pv.isConverted()) {
  58. // 如果属性值已经被转换过,直接保存
  59. deepCopy.add(pv);
  60. } else {
  61. // 如果没转换过
  62. // 获取键值对
  63. String propertyName = pv.getName();
  64. Object originalValue = pv.getValue();
  65. // 判断该属性是否是自动装配的标记
  66. if (originalValue == AutowiredPropertyMarker.INSTANCE) {
  67. // 获取该方法的写方法(setter方法)
  68. Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
  69. // 非空校验这个写方法
  70. if (writeMethod == null) {
  71. throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
  72. }
  73. // 将属性值替换为一个新的DependencyDescriptor对象,该对象表示对属性的依赖描述
  74. originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
  75. }
  76. // 解析该对象的属性值
  77. Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
  78. // 创建convertedValue,保存解析后的属性值,默认就是解析值
  79. Object convertedValue = resolvedValue;
  80. // 判断属性是否可转换,并且不是嵌套或索引属性。
  81. boolean convertible = bw.isWritableProperty(propertyName) &&
  82. !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
  83. if (convertible) {
  84. // 如果属性可转换,将解析后的属性值进行类型转换。
  85. convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
  86. }
  87. // 可能将转换后的值存储在合并的bean定义中,以避免对每个创建的bean实例进行重新转换。
  88. if (resolvedValue == originalValue) {
  89. // 如果解析后的值与原值相同
  90. if (convertible) {
  91. // 如果该属性可转换
  92. // 保存转换后的值进入pv
  93. pv.setConvertedValue(convertedValue);
  94. }
  95. // 将pv存入深拷贝数组
  96. deepCopy.add(pv);
  97. } else if (convertible && originalValue instanceof TypedStringValue &&
  98. !((TypedStringValue) originalValue).isDynamic() &&
  99. !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
  100. // 如果属性可转换且原始值是 TypedStringValue 类型且不是动态值,并且转换后的值不是集合或数组类型,
  101. // 则保存转换后的属性值,保存到深拷贝列表
  102. pv.setConvertedValue(convertedValue);
  103. deepCopy.add(pv);
  104. } else {
  105. // 标记需要解析,然后存到深拷贝列表
  106. resolveNecessary = true;
  107. deepCopy.add(new PropertyValue(pv, convertedValue));
  108. }
  109. }
  110. }
  111. // 如果mpvs不为空,且不需要解析,则标记为已转换
  112. if (mpvs != null && !resolveNecessary) {
  113. mpvs.setConverted();
  114. }
  115. // 4.将解析后的深拷贝列表set到BeanWrapper中
  116. try {
  117. bw.setPropertyValues(new MutablePropertyValues(deepCopy));
  118. } catch (BeansException ex) {
  119. throw new BeanCreationException(
  120. mbd.getResourceDescription(), beanName, "Error setting property values", ex);
  121. }
  122. }

4.4.4 resolveValueIfNecessary():根据类型解析属性

4.4.4.1 基本介绍

上面applyPropertyValues()方法调用了resolveValueIfNecessary()方法,该方法主要对当前属性的类型进行判断,根据实际的类型对属性进行解析。

又因为上面applyPropertyValues()方法调用本方式时,传参的属性是RuntimeBeanReference类型的,所以会执行下面逻辑,调用resolveReference()方法:

org.springframework.beans.factory.support.BeanDefinitionValueResolver

4.4.4.2 BeanDefinitionValueResolver类: 解析Bean的属性

BeanDefinitionValueResolver类位于org.springframework.beans.factory.support包下,主要用于解析 Bean 定义中的属性值。

具体功能:

  1. 解析属性值是否需要引用其他 Bean 或 Bean 名称,并进行相应的解析。对应方法resolveValueIfNecessary()、resolveReference();
  2. 解析包含的内部 Bean。对应方法resolveInnerBean();
  3. 解析数组、列表、集合、映射、属性等特殊类型的属性值。对应方法resolveManagedList()等;
  4. 将属性值转换为目标类型。对应方法resolveTargetType()等;

4.4.5 resolveReference():调用getBean()解析属性为Bean

上面 resolveValueIfNecessary()方法调用了resolveReference()方法,对属性进行解析。

本方法主要调用了getBean()方法,注册属性为Bean,然后获取到这个Bean。

核心流程:

  1. 获取Bean名:获取运行时 Bean 引用的名称。
  2. 获取Bean:根据引用的名称,调用 getBean() 方法从 BeanFactory 中获取对应的 Bean 实例。
  3. 空值校验、异常处理:如果没有获取到Bean返回空,如果有异常,加上错误信息并抛出异常;

详细流程:

org.springframework.beans.factory.support.BeanDefinitionValueResolver 

  1. /**
  2. * 在该方法中,会为当前初始化bean主要为属性注入另外一个bean,调用getBean()方法获取需要注入的bean,最终注入到属性中
  3. */
  4. private Object resolveReference(Object argName, RuntimeBeanReference ref) {
  5. try {
  6. Object bean;
  7. String refName = ref.getBeanName();
  8. refName = String.valueOf(doEvaluate(refName));
  9. if (ref.isToParent()) {
  10. if (this.beanFactory.getParentBeanFactory() == null) {
  11. throw new BeanCreationException(
  12. this.beanDefinition.getResourceDescription(), this.beanName,
  13. "Can't resolve reference to bean '" + refName +
  14. "' in parent factory: no parent factory available");
  15. }
  16. bean = this.beanFactory.getParentBeanFactory().getBean(refName);
  17. }
  18. else {
  19. // 当前初始化bean主要为属性注入另外一个bean,调用getBean()方法获取需要注入的bean,最终注入到属性中
  20. bean = this.beanFactory.getBean(refName);
  21. this.beanFactory.registerDependentBean(refName, this.beanName);
  22. }
  23. if (bean instanceof NullBean) {
  24. bean = null;
  25. }
  26. return bean;
  27. }
  28. catch (BeansException ex) {
  29. throw new BeanCreationException(
  30. this.beanDefinition.getResourceDescription(), this.beanName,
  31. "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
  32. }
  33. }

4.4.6 属性获取Bean流程:getBean() -> doGetBean()

4.4.6.1 直接从缓存中获取到AService

上面方法解析Bean的时候,调用了getBean()方法。

你可能在想,这不是无限套娃了吗?先调用getBean()获取AService,获取过程中,又调用getBean()获取属性BService,然后又调用getBean()获取AService属性,无限循环。

详细Bean加载流程参考:

Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程-CSDN博客

事实不是这样的。

这次执行doGetBean()的逻辑跟之前有所不同,主要原因是AService之前已经存入到第三级缓存中了,所以可以直接取到。

这是第二次获取AService了:

之前第一次获取AService的时候,上面getSingleton(String beanName)是没获取到数据的,是在doGetBean()后面执行getSingleton(String beanName, ObjectFactory<?> singletonFactory),这次就不再执行了,也就不再执行createBean()了:

4.4.6.2 getSingleton(beanName) :从缓存中获取单例Bean

本方法只有一行。

核心逻辑:

  • 调用getSingleton(String beanName, boolean allowEarlyReference)方法,传参true,代表允许循环依赖
  1. @Override
  2. @Nullable
  3. public Object getSingleton(String beanName) {
  4. return getSingleton(beanName, true);
  5. }
4.4.6.3 getSingleton(beanName,true):从缓存中获取单例Bean(是否允许循环依赖)

核心逻辑:

  1. 尝试从一级缓存中获取;
  2. 判断循环依赖:如果从一级缓存没取到,并且发生了循环依赖,则加锁执行下面逻辑:
  3. 尝试从二级缓存中获取;
  4. 从三级缓存中获取:如果获取到则执行Lambda表达式,生成提前代理对象,然后将其从三级缓存删除、存入二级缓存并返回;

提前代理对象:

提前代理对象是这一步执行第三级缓存的value,即一个Lambda表达式生成的(具体的实参参考上文的“存入第三级缓存”),因为这个对象还不是经历完整生命周期的Bean,还没有被IOC容器管理,只是用于解决循环依赖问题,所以称他为“提前代理对象”。

详细代码:

  1. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  2. // 从一级缓存获取BeanName对应的单例对象
  3. Object singletonObject = this.singletonObjects.get(beanName);
  4. // 如果没有获取到,但是当前 BeanName对应的单例对象又处于创建中
  5. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  6. synchronized (this.singletonObjects) {
  7. // 从二级缓存中获取当前BeanName对应的单例对象
  8. singletonObject = this.earlySingletonObjects.get(beanName);
  9. // 二级缓存中没有,但是allowEarlyReference为true,在doCreateBean方法中已经设置,所以这里为true
  10. if (singletonObject == null && allowEarlyReference) {
  11. // 从三级缓存中获取
  12. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  13. if (singletonFactory != null) {
  14. // 这里就是三级缓存函数方法,同过Factory创建一个单例对象
  15. singletonObject = singletonFactory.getObject();
  16. // 添加到二级缓存中,半成品对象
  17. this.earlySingletonObjects.put(beanName, singletonObject);
  18. // 同时删除三级缓存
  19. this.singletonFactories.remove(beanName);
  20. }
  21. }
  22. }
  23. }
  24. // 返回当前半成品对象
  25. return singletonObject;
  26. }

4.4.6.4 回顾doGetBean():getBean()的核心逻辑处理方法

详细参考下文: Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程-CSDN博客

getBean()只有一行代码,调用了doGetBean()一个方法。

do前缀的方法:

在Spring源码里边,有很多以do开头的方法,当你看到这些以do开头的方法时,应该意识到,在这个方法里边,往往才是真正的逻辑处理过程,即真正“干活”的方法。 

作用:根据给定的 Bean 名称、类型和参数获取 Bean 实例。

参数: 

  • name (String):要获取的 Bean 的名称。
    这个名称可能是原始的 Bean 名称,也可能是别名,或者是带有 & 前缀的 FactoryBean 名称。
  • requiredType (Class<T>):指定要返回的 Bean 的类型。
    如果不指定类型或者类型为 null,则返回任何类型的 Bean。
  • args (Object[]):构造方法参数数组。
    如果 Bean 有构造方法,这些参数将传递给构造函数进行实例化。如果 Bean 没有构造函数或者不需要参数,这个参数可以为 null。
  • typeCheckOnly (boolean):是否只检查类型。
    表示是否只进行类型检查而不实际获取 Bean 实例。如果为 true,则只会检查 Bean 是否符合指定的类型,不会真正实例化 Bean。

流程概述: 

  1. 提取beanName;
  2. 尝试从缓存获取Bean:调用getSingleton(String beanName),如果当前Bean已经被加载过获取因为循环依赖正咋被加载,这里将直接获取到Bean实例;
  3. 循环依赖的判断。
  4. 递归去父容器获取Bean实例。
  5. 从当前容器获取BeanDefinition实例。
  6. 递归实例化显式依赖的Bean。
  7. 根据不同的Scope采用不同的策略创建Bean实例:调用getSingleton(String beanName, ObjectFactory<?> singletonFactory),传参Lambda表达式中有createBean()去创建Bean。
  8. 对Bean进行类型检查。 

流程详解:

org.springframework.beans.factory.support.AbstractBeanFactory 

  1. protected <T> T doGetBean(
  2. String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
  3. throws BeansException {
  4. // 1. 提取出对应的beanName。
  5. // 将参数name(1.FactoryBean要去掉前缀&,2.别名A指向B的Bean要转成B)转换成容器中真实的bean名称(获取容器中真实beanName)
  6. String beanName = transformedBeanName(name);
  7. Object bean;
  8. // 2.尝试直接从三级缓存中获取Bean
  9. // 尝试从一级缓存中获取之前被实例化过了的单例bean或从三级缓存中获取ObjectFactory,执行Lambda表达式创建单例Bean。
  10. // 如果当前Bean已经被加载过,或者因为循环依赖处在加载中,就可以直接从这个getSingleton(beanName)中获取到Bean,
  11. // 否则就要执行后面第8步的getSingleton(beanName,包含createBean的Lambda)
  12. Object sharedInstance = getSingleton(beanName);
  13. // 如果之前已经创建过该单例bean,并且args为空(单例 bean不可以用这个args,它是为多例设计的)
  14. if (sharedInstance != null && args == null) {
  15. if (logger.isDebugEnabled()) {
  16. // 如果Bean还在创建中,则说明是循环依赖.
  17. if (isSingletonCurrentlyInCreation(beanName)) {
  18. logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
  19. "' that is not fully initialized yet - a consequence of a circular reference");
  20. }
  21. else {
  22. logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
  23. }
  24. }
  25. // 3. 检测处理FactoryBean类型的bean并返回实例。
  26. // 如果是普通的bean,直接返回,如果是factoryBean,则返回它的getObject. 这一步主要还是针对FactoryBean的处理。
  27. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  28. }
  29. // 如果scope->prototype,singleton.但是在缓存中无法找到
  30. else {
  31. // Fail if we're already creating this bean instance:
  32. // We're assumably within a circular reference.
  33. // 4. 先根据缓存判断一下当前的bean是否正在被创建,如果是的话表示依赖循环了;只有单例情况才会尝试解决循环依赖,原型模式直接抛出异常。因为原型模式无法解决循环依赖问题。
  34. if (isPrototypeCurrentlyInCreation(beanName)) {
  35. throw new BeanCurrentlyInCreationException(beanName);
  36. }
  37. // Check if bean definition exists in this factory.
  38. // 5. 获取父级的BeanFactory
  39. BeanFactory parentBeanFactory = getParentBeanFactory();
  40. // 如果在当前容器中无法找到指定名称的bean,此时递归去parentFactory查找.
  41. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  42. // Not found -> check parent.
  43. // 递归到BeanFactory中检测,针对FactoryBean,将Bean的&重新拼上
  44. String nameToLookup = originalBeanName(name);
  45. // 如果parentBeanFactory属于AbstractBeanFactory实例
  46. if (parentBeanFactory instanceof AbstractBeanFactory) {
  47. // 递归查找
  48. return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
  49. nameToLookup, requiredType, args, typeCheckOnly);
  50. }
  51. else if (args != null) {
  52. // Delegation to parent with explicit args.
  53. // 如果有参数,则委派父级容器根据指定名称和显式的参数查找.
  54. return (T) parentBeanFactory.getBean(nameToLookup, args);
  55. }
  56. else {
  57. // No args -> delegate to standard getBean method.
  58. // 如果没有参数,委托父级容器根据指定名称和type进行查找
  59. return parentBeanFactory.getBean(nameToLookup, requiredType);
  60. }
  61. }
  62. // 如果当前要获取的bean只是为了进行类型检查就标记bean已经被创建
  63. if (!typeCheckOnly) {
  64. // 这里是将 当前创建的beanName 保存到 alreadyCreated 集合中。alreadyCreated 中的bean表示当前bean已经创建了,在进行循环依赖判断的时候会使用
  65. markBeanAsCreated(beanName);
  66. }
  67. try {
  68. // 6. 将当前 beanName 的 BeanDefinition 和父类BeanDefinition 属性进行一个整合
  69. RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  70. // 对合并的BeanDefiniton进行检测,主要判断是否为abstract.
  71. checkMergedBeanDefinition(mbd, beanName, args);
  72. // Guarantee initialization of beans that the current bean depends on.
  73. // 7. 寻找bean的依赖
  74. // 获取当前Bean所有依赖的Bean名称
  75. String[] dependsOn = mbd.getDependsOn();
  76. // 如果需要依赖,则递归实例化依赖bean
  77. if (dependsOn != null) {
  78. for (String dep : dependsOn) {
  79. // 判断是否有循环依赖的情况 : A依赖B,B依赖A
  80. if (isDependent(beanName, dep)) {
  81. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  82. "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
  83. }
  84. // 注册依赖信息,将依赖信息保存到 dependentBeanMap、dependenciesForBeanMap中
  85. registerDependentBean(dep, beanName);
  86. try {
  87. // 获取依赖的bean,这一步又回到了最初的getBean
  88. getBean(dep);
  89. }
  90. catch (NoSuchBeanDefinitionException ex) {
  91. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  92. "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
  93. }
  94. }
  95. }
  96. // Create bean instance.
  97. // 8 针对不同的Scope 进行bean的创建
  98. // 实例化依赖的bean便可以实例化mdb本身了
  99. // 如果BeanDefiniton为单例
  100. if (mbd.isSingleton()) {
  101. // 匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
  102. // 关键方法:单例类实例化的入口
  103. sharedInstance = getSingleton(beanName, () -> {
  104. try {
  105. // 创建单例bean的入口.
  106. // =============关键===============
  107. return createBean(beanName, mbd, args);
  108. }
  109. catch (BeansException ex) {
  110. // Explicitly remove instance from singleton cache: It might have been put there
  111. // eagerly by the creation process, to allow for circular reference resolution.
  112. // Also remove any beans that received a temporary reference to the bean.
  113. // 显性从单例缓存中删除bean实例.
  114. // 因为单例模式下为了解决循环依赖,可能留有残余的信息,此处进行销毁
  115. destroySingleton(beanName);
  116. throw ex;
  117. }
  118. });
  119. // 解决FactoryBean的问题
  120. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  121. }
  122. else if (mbd.isPrototype()) {
  123. // It's a prototype -> create a new instance.
  124. // 原型模式的回调
  125. // 如果是原型模式,创建一个实例,在原型模式下,每次getBean都会产生一个新的实例
  126. Object prototypeInstance = null;
  127. try {
  128. // 保存当前线程正在创建的beanName 到 prototypesCurrentlyInCreation 中
  129. beforePrototypeCreation(beanName);
  130. // 直接创建bean
  131. prototypeInstance = createBean(beanName, mbd, args);
  132. }
  133. finally {
  134. // 完成创建后,从 prototypesCurrentlyInCreation 中移除当前线程正在创建的beanName
  135. afterPrototypeCreation(beanName);
  136. }
  137. // 解决FactoryBean的问题
  138. bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
  139. }
  140. else {
  141. // 指定scope上实例化bean
  142. String scopeName = mbd.getScope();
  143. if (!StringUtils.hasLength(scopeName)) {
  144. throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
  145. }
  146. Scope scope = this.scopes.get(scopeName);
  147. if (scope == null) {
  148. throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
  149. }
  150. try {
  151. Object scopedInstance = scope.get(beanName, () -> {
  152. // 保存当前线程正在创建的beanName 到 prototypesCurrentlyInCreation 中
  153. beforePrototypeCreation(beanName);
  154. try {
  155. // 创建bean
  156. return createBean(beanName, mbd, args);
  157. }
  158. finally {
  159. // 移除当前线程正在创建的beanName 从 prototypesCurrentlyInCreation 中
  160. afterPrototypeCreation(beanName);
  161. }
  162. });
  163. // 解决FactoryBean的问题
  164. bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
  165. }
  166. catch (IllegalStateException ex) {
  167. throw new BeanCreationException(beanName,
  168. "Scope '" + scopeName + "' is not active for the current thread; consider " +
  169. "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
  170. ex);
  171. }
  172. }
  173. }
  174. catch (BeansException ex) {
  175. cleanupAfterBeanCreationFailure(beanName);
  176. throw ex;
  177. }
  178. }
  179. // Check if required type matches the type of the actual bean instance.
  180. // 9 类型转换
  181. // 检查需要的类型是否符合bean 的实际类型
  182. if (requiredType != null && !requiredType.isInstance(bean)) {
  183. try {
  184. T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
  185. if (convertedBean == null) {
  186. throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
  187. }
  188. return convertedBean;
  189. }
  190. catch (TypeMismatchException ex) {
  191. if (logger.isDebugEnabled()) {
  192. logger.debug("Failed to convert bean '" + name + "' to required type '" +
  193. ClassUtils.getQualifiedName(requiredType) + "'", ex);
  194. }
  195. throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
  196. }
  197. }
  198. return (T) bean;
  199. }

4.5 doCreateBean的其他逻辑

在属性填充后,AService将执行doCreateBean()剩余的逻辑,即AOP增强、校验依赖注册、注册销毁Bean,也就是下面流程中的6,7,8,执行完后,这个Bean以及它的依赖都已经注册完毕:

  1. 判断单例:创建一个BeanWrapper,如果是单例,则取出缓存赋值给它,并清除缓存
  2. wrapper为空时实例化Bean:调用createBeanInstance()方法,默认用无参构造方法实例化Bean,赋值给wrapper
  3. 合并处理BeanDefinition:应用所有已注册的 MergedBeanDefinitionPostProcessor (用于修改或扩展BeanDefinition)到给定的 BeanDefinition 实例
  4. 放进三级缓存:当Bean是单例、允许循环依赖时,将Lambda表达式放进三级缓存,以后如果执行这个Lambda表达式,生成的将是BService的提前代理对象;
  5. 属性填充:填充注解@Autowired、@Resource、@Value等的属性
  6. 初始化bean:调用initializeBean()方法,初始化和aop,通过JDK的Proxy.newProxyInstance()实现动态代理,返回目标对象的代理对象,对Bean进行增强。
    1. 执行所有BeanPostProcessor的初始化前方法:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessBeforeInitialization()方法。本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。
    2. 初始化:如果Bean实例实现了InitializingBean接口(通过instanceof判断),调用Bean重写的afterPropertiesSet()方法,处理初始化逻辑。afterPropertiesSet译为“在属性填充之后”
    3. 执行所有BeanPostProcessor的初始化后方法:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessAfterInitialization()方法。本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。
  7. 校验依赖注册为Bean:获取所有注入属性,检查这些属性是否已被注册为Bean,如果存在依赖没注册为Bean,则抛出异常
  8. 注册销毁Bean:调用registerDisposableBeanIfNecessary()方法,注册DisposableBean,以便在销毁bean 的时候可以运行指定的相关业务。
    1. 判断实现DisposableBean接口:当前Bean是否实现了DisposableBean接口,是则直接返回true;否则进行【推断销毁方法】流程
    2. 推断销毁方法:
      1. 寻找当前bean下是否有close方法或者shutdown方法,或者是否实现了AutoCloseable接口,是则直接返回销毁方法名称
      2. 感知销毁Bean后置处理器:如果【推断销毁方法】也没有结果,则调用【感知销毁Bean后置处理器】DestructionAwareBeanPostProcessor.requiresDestruction(bean)判断,如果当前bean是ApplicationListener子类需要销毁,拥有@PreDestroy注解了的方法就是需要销毁
    3. 适配成DisposableBeanAdapter对象:如果需要销毁,则适配成DisposableBeanAdapter对象,并存入disposableBeans中(一个LinkedHashMap<String, Object>)

详细解析:

 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

  1. /**
  2. * 创建Bean的核心逻辑处理方法
  3. *
  4. * @param beanName bean名称
  5. * @param mbd BeanDefinition对象
  6. * @param args 构造函数参数
  7. * @return {@link Object}
  8. * @throws BeanCreationException Bean创建异常
  9. */
  10. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
  11. throws BeanCreationException {
  12. // 1.判断单例:创建一个BeanWrapper,如果是单例,则取出缓存赋值给它,并清除缓存
  13. BeanWrapper instanceWrapper = null;
  14. // 如果BeanDefinition是单例模式,就先从缓存中清除
  15. if (mbd.isSingleton()) {
  16. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  17. }
  18. // 2.wrapper为空时实例化Bean:调用createBeanInstance()方法,默认用无参构造方法实例化Bean,赋值给wrapper
  19. // bean初始化第一步:默认调用无参构造实例化Bean
  20. // 构造参数依赖注入,就是发生在这一步
  21. if (instanceWrapper == null) {
  22. instanceWrapper = createBeanInstance(beanName, mbd, args);
  23. }
  24. // 实例化后的Bean对象
  25. final Object bean = instanceWrapper.getWrappedInstance();
  26. Class<?> beanType = instanceWrapper.getWrappedClass();
  27. if (beanType != NullBean.class) {
  28. // 将 解析类型 设置 为 beanType
  29. mbd.resolvedTargetType = beanType;
  30. }
  31. // Allow post-processors to modify the merged bean definition.
  32. // 使用后置处理器 对其进行处理
  33. synchronized (mbd.postProcessingLock) {
  34. if (!mbd.postProcessed) {
  35. try {
  36. // 合并处理BeanDefinition:应用所有已注册的 MergedBeanDefinitionPostProcessor (用于修改或扩展BeanDefination)到给定的 BeanDefinition 实例
  37. //对@Autowire,@Value等这些注解进行处理
  38. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  39. } catch (Throwable ex) {
  40. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  41. "Post-processing of merged bean definition failed", ex);
  42. }
  43. mbd.postProcessed = true;
  44. }
  45. }
  46. // 3.存入三级缓存:当Bean是单例、允许循环依赖时,将Lambda表达式放进三级缓存,以后如果执行这个Lambda表达式,生成的将是BService的提前代理对象;
  47. // Eagerly cache singletons to be able to resolve circular references
  48. // even when triggered by lifecycle interfaces like BeanFactoryAware.
  49. /**是否需要提前曝光: 单例& 允许循环依赖 & 当前bean正在创建中, 检查循环依赖
  50. 这里主要是调用 方法addSingletonFactory ,往缓存singletonFactories里面 放入一个 ObjectFactory
  51. 当其他的bean 对该bean 有依赖时,可以提前获取到
  52. getEarlyBeanReference方法就是获取一个引用, 里面主要是
  53. 调用了 SmartInstantiationAwareBeanPostProcessor,
  54. 的 getEarlyBeanReference 方法,以便解决循环依赖问题, 这里 一般都是bean 本身,
  55. 在 AOP时 是代理
  56. **/
  57. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  58. isSingletonCurrentlyInCreation(beanName));
  59. if (earlySingletonExposure) {
  60. if (logger.isTraceEnabled()) {
  61. logger.trace("Eagerly caching bean '" + beanName +
  62. "' to allow for resolving potential circular references");
  63. }
  64. // 将刚创建的bean放入三级缓存中,singleFactories(key是beanName,value是ObjectFactory)
  65. // 注意此处实参又是一个lambda表达式,
  66. // 即参数传入的是ObjectFactory类型一个匿名内部类对象,在后续再缓存中查找Bean时会触发匿名内部类getEarlyBeanReference()方法回调
  67. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  68. }
  69. // 4.依赖处理
  70. // Initialize the bean instance.
  71. Object exposedObject = bean;
  72. // 下面就是初始化实例了
  73. try {
  74. // 5.填充属性(DI依赖注入发生在此步骤)
  75. // 对bean进行填充,将各个属性值注入,其中可能存在依赖于其他bean的属性,会递归初始化
  76. populateBean(beanName, mbd, instanceWrapper);
  77. // 6.初始化bean:初始化和aop,通过JDK的Proxy.newProxyInstance()实现动态代理,返回目标对象的代理对象,对Bean进行增强。
  78. // AOP是通过自动代理创建器AbstractAutoProxyCreator的postProcessAfterInitialization()
  79. //方法的执行进行代理对象的创建的,AbstractAutoProxyCreator是BeanPostProcessor接口的实现类
  80. //进一步初始化Bean
  81. //注入 Aware 相关的对象
  82. // 调用 后置处理器 BeanPostProcessor 里面的postProcessBeforeInitialization方法
  83. // 调用 initialzingBean,调用实现的 afterPropertiesSet()
  84. // 调用 init-mothod,调用相应的init方法
  85. // 调用 后置处理器 BeanPostProcessor 里面的调用实现的postProcessAfterInitialization方法
  86. exposedObject = initializeBean(beanName, exposedObject, mbd);
  87. } catch (Throwable ex) {
  88. if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
  89. throw (BeanCreationException) ex;
  90. } else {
  91. throw new BeanCreationException(
  92. mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
  93. }
  94. }
  95. if (earlySingletonExposure) {
  96. Object earlySingletonReference = getSingleton(beanName, false);
  97. // earlySingletonReference 只有在检测到有循环依赖的情况下才会不为空
  98. if (earlySingletonReference != null) {
  99. //如果exposedObject 没有在初始化方法中被改变,也就是没有被增强
  100. if (exposedObject == bean) {
  101. exposedObject = earlySingletonReference;
  102. } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
  103. // 7.依赖检查:获取所有注入属性,检查这些属性是否已被注册为Bean
  104. String[] dependentBeans = getDependentBeans(beanName);
  105. Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
  106. // 检查依赖
  107. for (String dependentBean : dependentBeans) {
  108. if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
  109. actualDependentBeans.add(dependentBean);
  110. }
  111. }
  112. /**
  113. 因为 bean 创建后其所依赖的bean一定是已经创建,
  114. actualDependentBeans 不为空则表示 当前bean 创建后其依赖的bean 却没有全部创建,
  115. 也就是说存在依赖
  116. */
  117. if (!actualDependentBeans.isEmpty()) {
  118. throw new BeanCurrentlyInCreationException(beanName,
  119. "Bean with name '" + beanName + "' has been injected into other beans [" +
  120. StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
  121. "] in its raw version as part of a circular reference, but has eventually been " +
  122. "wrapped. This means that said other beans do not use the final version of the " +
  123. "bean. This is often the result of over-eager type matching - consider using " +
  124. "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
  125. }
  126. }
  127. }
  128. }
  129. // 8.注册销毁Bean
  130. try {
  131. registerDisposableBeanIfNecessary(beanName, bean, mbd);
  132. } catch (BeanDefinitionValidationException ex) {
  133. throw new BeanCreationException(
  134. mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  135. }
  136. return exposedObject;
  137. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/919802
推荐阅读
相关标签
  

闽ICP备14008679号