导航:
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
目录
3.2 源码位置:DefaultSingletonBeanRegistry类
4.1.1 方法调用链:getBean() -> doGetBean() -> getSingleton() -> createBean() -> doCreateBean()
4.2.2 详解createBeanInstance():推断构造方法并实例化Bean
4.3.2 addSingletonFactory():存入第三级缓存
4.3.3 getEarlyBeanReference():生成提前代理对象
4.4.3 applyPropertyValues():解析、转换所有属性
4.4.4 resolveValueIfNecessary():根据类型解析属性
4.4.4.2 BeanDefinitionValueResolver类: 解析Bean的属性
4.4.5 resolveReference():调用getBean()解析属性为Bean
4.4.6 属性获取Bean流程:getBean() -> doGetBean()
4.4.6.2 getSingleton(beanName) :从缓存中获取单例Bean
4.4.6.3 getSingleton(beanName,true):从缓存中获取单例Bean(是否允许循环依赖)
4.4.6.4 回顾doGetBean():getBean()的核心逻辑处理方法
一、概念准备
1.1 循环依赖
Spring循环依赖:在Spring应用程序中两个或多个Bean彼此之间存在直接或间接的依赖关系,并且这种依赖关系形成了一个循环。
简而言之,循环依赖就是Bean A注入了Bean B,同时Bean B注入了Bean A,那么这两个Bean就形成了一个依赖关系。
举例:
举个例子,以下代码中,AService和BService就形成了一个循环依赖关系:
AService注入BService:
/** * @Author: vince * @CreateTime: 2024/03/15 * @Description: AService * @Version: 1.0 */ @Component public class AService { /** * 注入BService */ @Resource private BService bService; }
BService注入AService:
/** * @Author: vince * @CreateTime: 2024/03/15 * @Description: BService * @Version: 1.0 */ @Component public class BService { /** * 注入AService */ @Resource private AService aService; }
1.2 Bean的生命周期
源码解析:
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:
/** * @Author: vince * @CreateTime: 2024/03/15 * @Description: AService * @Version: 1.0 */ @Component public class AService { /** * 注入BService */ @Resource private BService bService; }
BService注入AService:
/** * @Author: vince * @CreateTime: 2024/03/15 * @Description: BService * @Version: 1.0 */ @Component public class BService { /** * 注入AService */ @Resource private AService aService; }
测试类获取Bean
/** * @Author: vince * @CreateTime: 2024/03/20 * @Description: 测试类:循环依赖 * @Version: 1.0 */ public class Test { public static void main(String[] args) { // 1.获取Spring容器,加载配置类 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 2.从容器中获取AService对象 AService aService = context.getBean("AService", AService.class); } }
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 方法二(推荐):覆盖类(基于双亲委派模型)
类加载机制和双亲委派模型:
双亲委派模型这里不再过多赘述,详情看上面文章。
基于双亲委派模型,我们可以在本地创建一个与原始类路径、全限定名完全一致的类,就可以实现对原类的覆盖,代码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:
/** * 一级缓存,value是经过完整生命周期的Bean */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** * 二级缓存,value是提前代理对象 */ private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); /** * 三级缓存,value是Lambda表达式(ObjectFactory是一个函数式接口) * 函数式接口可以把匿名内部类、lambda表达式作为参数传递到方法中 */ 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
package java.util.function; /** * Represents a supplier of results. */ @FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); }
应用案例:使用Supplier,获取数组中的最大值:
/** * @Author: vince * @CreateTime: 2024/03/20 * @Description: 测试类 * @Version: 1.0 */ public class Test { /** * 主方法 * @param args 参数 */ public static void main(String[] args) { // 定义一个int数组 int[] arr = {19, 50, 28, 37, 46}; // 调用getMax方法,方法的形参是函数式接口(单方法接口), // 实参Lambda表达式(接口方法的逻辑,相当于创建了一个Supplier对象) // 返回值是Lambda表达式的返回值,sup.get() int maxValue = getMax(() -> { int max = arr[0]; for (int i = 1; i < arr.length; i++) { if (arr[i] > max) { max = arr[i]; } } return max; }); System.out.println(maxValue); } /** * 返回一个int数组中的最大值,具体的逻辑由实参Lambda表达式决定 * @param sup 供应商 * @return int 最大值 */ private static int getMax(Supplier<Integer> sup) { return sup.get(); } }
3.3.2 ObjectFactory
第三级缓存:
首先我们看第三级缓存,它的value是ObjectFactory接口
/** * 三级缓存,value是Lambda表达式(ObjectFactory是一个函数式接口) * 函数式接口可以把匿名内部类、lambda表达式作为参数传递到方法中 */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
什么是ObjectFactory?
ObjectFactory是一个函数式接口,因为它包含@FunctionalInterface注解。
它只有一个getObject()方法,用于获取实参Lambda表达式生成的Bean对象。
@FunctionalInterface public interface ObjectFactory<T> { /** * Return an instance (possibly shared or independent) * of the object managed by this factory. * @return the resulting instance * @throws BeansException in case of creation errors */ T getObject() throws BeansException; }
使用示例:
将获取存储进三级缓存:
函数式接口是一般都是形参,可以把匿名内部类、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的创建过程:
- 推断和实例化;
- 存入三级缓存;
- 属性填充BService,BService创建流程:
- 推断和实例化
- 存入三级缓存
- 属性填充AService
- 单例池找
- 判断循环依赖
- 二级缓存找
- 三级缓存找到,生成提前代理对象、存二级缓存
- 执行三级缓存
- 存入单例池
- AOP包裹初始化
- 存入单例池
解释: 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容器,需要使用应用容器上下文加载配置类:
/** * @Author: vince * @CreateTime: 2024/03/20 * @Description: 测试类:循环依赖 * @Version: 1.0 */ public class Test { public static void main(String[] args) { // 1.注解方式启动IOC容器,加载配置类 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 2.调用TestService的test()方法 TestService testService = context.getBean(TestService.class, "testService"); testService.test(); } }
AnnotationConfigApplicationContext的构造方法会调用this.refresh();,它会调用finishBeanFactoryInitialization()方法初始化所有单例bean,然后调用preInstantiateSingletons()方法,它调用了getBean()。
这个调用链此处不再累述,详细参考下文:
这个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的核心逻辑处理方法
4.2 推断并实例化Bean
4.2.1 核心流程
- 判断单例:创建一个BeanWrapper,如果是单例,则取出缓存赋值给它,并清除缓存
- wrapper为空时实例化Bean:调用createBeanInstance()方法,默认用无参构造方法实例化Bean,赋值给wrapper
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
AbstractAutowireCapableBeanFactory是上面定义三级缓存的类DefaultSingletonBeanRegistry的子类,用于bean 初始化和自动装配(使用三级缓存解决了循环依赖),核心方法是autowireBean()、createBean()、doCreateBean()。
详见下文2.5.2:
// 1.判断单例:创建一个BeanWrapper,如果是单例,则取出缓存赋值给它,并清除缓存 BeanWrapper instanceWrapper = null; // 如果BeanDefinition是单例模式,就先从缓存中清除 if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } // 2.wrapper为空时实例化Bean:调用createBeanInstance()方法,默认用无参构造方法实例化Bean,赋值给wrapper // bean初始化第一步:默认调用无参构造实例化Bean // 构造参数依赖注入,就是发生在这一步 if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); }
上面代码中核心代码是下面一行,调用调用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
/** * 根据BeanDefinition中的信息,创建Bean实例 * * @param beanName Bean的名称 * @param mbd Bean的定义信息 * @param args 构造器参数 * @return {@link BeanWrapper} */ protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 1.获取Bean 的Class对象,用于获取类的属性和调用newInstance()方法实例化 // 解析Bean的类型,确认需要创建的bean实例的类可以实例化。 // 如果没有设置通过Class.forName获取Bean类型 Class<?> beanClass = resolveBeanClass(mbd, beanName); // 2.校验 Bean 必须非空且public:如果 Bean 类型为null、或者不是公共类,则抛出异常。 // 确保class不为空,并且访问权限是public if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } // 3.判断是否使用Supplier创建 Bean:如果 BeanDefinition 中包含实例供应器Supplier,则调用该实例供应器来创建 Bean 实例。 // ①Supplier方式创建Bean: 需要先有回调Bean // 判断当前beanDefinition中是否包含实例供应器,此处相当于一个回调方法,利用回调方法来创建bean Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } // 4.判断是否使用工厂方法创建 Bean: BeanDefinition 中配置了工厂方法,则尝试调用该工厂方法来创建 Bean 实例。 // ②FactoryMethod方式创建Bean: 需要在XML中配置factory-method // 判断是否有工厂方法,如果存在,会尝试调用该Bean定义信息中的工厂方法来获取实例 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // 5.判断构造函数是否缓存过: // 如果已经解析过 Bean 类型的构造函数,并且不需要自动装配,则直接使用缓存的构造函数或默认构造函数来创建 Bean 实例。 // 缓存位置在BeanDefinition 的resolvedConstructorOrFactoryMethod字段; // 缓存值的类型是Executable(代表可执行的程序单元,可以是普通方法或者构造方法,可以通过它获取方法的参数类型、个数等信息) // Shortcut when re-creating the same bean... //一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器,当多次构建同一个 bean 时就不需要重新判断应该使用那种方式构造Bean boolean resolved = false; //是否需要自动装配 boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { // 因为判断过程会比较慢,所以spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod字段中。 // 在下次创建相同时直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值获取,避免再次解析,导致循环依赖 // 这个字段是一个包可见的字段,用于缓存已解析的构造函数或工厂方法。 if (mbd.resolvedConstructorOrFactoryMethod != null) { //标识以及解析过class的构造器 resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } // 6.判断是否需要自动装配构造函数:如果存在可选构造函数、设置了构造参数值、有参与构造函数参数列表的参数或者配置了构造函数自动装配,则进入自动装配构造函数的流程。 // 有构造参数的或者工厂 if (resolved) { //已经解析过class的构造器,使用已经解析好的构造器 if (autowireNecessary) { //构造函数自动注入 return autowireConstructor(beanName, mbd, null, null); } else { //使用默认构造器 return instantiateBean(beanName, mbd); } } // 7.后置处理器中寻找候选构造函数:从 Bean 的后置处理器中寻找候选构造函数,这些构造函数可能是通过 @Autowired 注解标注的构造函数或者是通过其他方式标注的。 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); // 8.推断构造函数并自动装配:根据候选构造函数和参数来确定最终的构造函数,并进行自动装配。 // 从bean后置处理器中为自动装配寻找构造方法 // 以下情况符合其一即可进入 // 1、存在可选构造方法 // 2、自动装配模型为构造函数自动装配 // 3、给BeanDefinition中设置了构造参数值 // 4、有参与构造函数参数列表的参数 if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // Preferred constructors for default construction? // 从bean后置处理器中为自动装配寻找构造方法, 有且仅有一个有参构造或者有且仅有@Autowired注解构造 ctors = mbd.getPreferredConstructors(); if (ctors != null) { // 构造函数自动注入 // 二、有参构造创建Bean return autowireConstructor(beanName, mbd, ctors, null); } // No special handling: simply use no-arg constructor. // 使用默认无参构造函数创建对象,如果没有无参构造且存在多个有参构造且没有@AutoWired注解构造,会报错 //三、无参构造创建Bean return instantiateBean(beanName, mbd); }
4.3 存入第三级缓存
4.3.1 概述
在上面doCreateBean()的第四步——"依赖处理"阶段,调用了下面这一行代码,将实例化后的Bean存入三级缓存,key是beanName,value是ObjectFactory(形参是这个函数式接口,实参是Lambda表达式):
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
/** * 为指定的 bean 名称的Bean,添加到第三级缓存。 * * @param beanName bean 的名称 * @param singletonFactory bean 的单例工厂 * @throws IllegalArgumentException 如果单例工厂为 {@code null} */ protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { // 1.如果一级缓存里没有这个Bean,就放入三级缓存、移除二级缓存;如果有就代表这个Bean被加载过,无需操作 if (!this.singletonObjects.containsKey(beanName)) { // 放入三级缓存 this.singletonFactories.put(beanName, singletonFactory); // 从二级缓存移除 this.earlySingletonObjects.remove(beanName); // 添加到已注册单例的集合中 this.registeredSingletons.add(beanName); } } }
4.3.3 getEarlyBeanReference():生成提前代理对象
核心逻辑:
- 生成提前代理对象:执行Lambda表达式,遍历所有后置处理器BeanPostProcessor,生产提前代理对象。因为这个对象还不是经历完整生命周期的Bean,还没有被IOC容器管理,只是用于解决循环依赖问题,所以称他为“提前代理对象”。
具体代码:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
/** * 获取指定 bean 的提前代理对象,通常用于解决循环引用的目的。 * * @param beanName bean 的名称(用于错误处理目的) * @param mbd bean 的合并后的 BeanDefinition * @param bean 原始的 bean 实例 * @return 要暴露为 bean 引用的对象 */ protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { // 默认情况下,暴露对象(即提前代理对象)为原始的 bean 实例 Object exposedObject = bean; // 遍历所有后置处理器BeanPostProcessor,增强暴露对象 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { // 遍历所有 BeanPostProcessor for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) { exposedObject = bp.getEarlyBeanReference(exposedObject, beanName); } } return exposedObject; }
4.4 属性填充:解决循环依赖在这一步完成
4.4.1 概述
Bean创建过程的核心方法doCreateBean(),第5步是依赖填充,将当前Bean注入的各个包含@Value,@Autowired,@Resource等注解的属性进行填充,这些注入的Bean可能还没有初始化,也可能初始化过并且它们的属性也包含当前Bean,这就产生了循环依赖,这个步骤使用三级缓存解决了循环依赖。
// 5.填充属性(DI依赖注入发生在此步骤) // 对bean进行填充,将各个属性值注入,其中可能存在依赖于其他bean的属性,会递归初始化 populateBean(beanName, mbd, instanceWrapper);
4.4.2 populateBean():属性填充
核心流程:
- 执行所有后置处理器(实例化后):判断当前Bean是否实现了后置处理器InstantiationAwareBeanPostProcessor接口,如果实现了,则执行postProcessPropertyValues()方法,这个方法专门在Bean的属性注入之前调用;
- 自动装配:判断根据名称注入,还是按类型自动注入,然后调用autowireByName()或autowireByType()注入;
- 依赖检查:如果依赖注入后的属性值为空,并且没有过滤需要进行依赖检查的 PropertyDescriptor 集合,则过滤并检查;
- 将属性应用到bean中:对属性值解析和转换,确保属性值能够正确地应用到 Bean 实例中;
/** * 属性填充方法,给定一个bean名称,根Bean定义和Bean包装器,为Bean设置属性值。 * * @param beanName bean的名称 * @param mbd bean的根Bean定义 * @param bw bean的Bean包装器 */ protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // 空值校验 if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } /** * 1.执行属性注入前后置处理器 * 这里调用了 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation方法 * 给InstantiationAwareBeanPostProcessor最后一次机会在属性设置前来改变bean * 注意:如果实现这个类并且在postProcessAfterInstantiation()返回 false 可以导致其他实例无法注入 */ if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); int resolvedAutowireMode = mbd.getResolvedAutowireMode(); // 2.按名或类型自动装配: // 根据名称或类型自动注入,从Spring2.5开始,开始支持使用注解(@Autowired)来自动装配Bean的属性 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; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // 3.依赖检查 boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { // 对于每一个后置处理器,如果是 InstantiationAwareBeanPostProcessor 的实现类,则调用其 postProcessProperties 方法来进行依赖注入过程。 if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 依赖注入过程 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { // 过滤出需要进行依赖检查的PropertyDescriptor集合,用于: // 1、若存在InstantiationAwareBeanPostProcessor类型的后置处理器, // 则各属性调用postProcessPropertyValues 方法(在Bean的属性注入之前调用),这些属性是由上述的过滤方法过滤得到; // 2、后续检查需要设置值的属性是否已经初始化;作用也是用于筛选需要处理的属性,个人感觉这部分使用是扩展和辅助检查,更重要的是“第一处”中的使用。 filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 老版本用这个方式去注入 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 依赖检查,对应 depends-on 属性,3.0 已弃用,这里不在分析 checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { // 4.将属性应用到bean中: // 对属性值解析和转换,确保属性值能够正确地应用到 Bean 实例中; applyPropertyValues(beanName, mbd, bw, pvs); } }
4.4.3 applyPropertyValues():解析、转换所有属性
上面populateBean()方法第四步调用了 applyPropertyValues()方法,这个方法主要作用是将所有属性统一注册为Bean。它遍历所有属性并解析加到深拷贝列表,解析完所有属性后应用到bean。为了不影响到BeanDefinition的属性集合才使用深拷贝。
核心逻辑:
- 非空校验:如果属性值列表是空的,结束注入流程;
- 判断属性值列表的类型:将转换过的属性赋值到BeanWrapper的对应属性中,然后转为List集合,交给original;
- 遍历属性值列表:如果每个属性转换过则直接加入深拷贝列表中,如果没转换过则将属性解析、转换后加入deepCopy;
- 将解析后的属性值列表赋值给BeanWrapper:将解析后的深拷贝列表转为MutablePropertyValues类型后,set到BeanWrapper中;
具体代码:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
/** * 将所有属性统一注册为Bean:遍历所有属性并解析加到深拷贝列表,解析完所有属性后应用到bean。 * 将给定的属性值应用到 Bean 实例中,同时解析任何运行时引用到此 Bean 工厂中的其他 Bean。 * 在这个过程中,必须进行深度拷贝,以避免永久修改属性。 * * @param beanName Bean的名称 * @param mbd Bean的定义信息 * @param bw BeanWrapper对象 * @param pvs 属性值列表 */ protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { // 1.非空校验:如果属性值列表是空的,结束注入流程 if (pvs.isEmpty()) { return; } if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) { ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); } MutablePropertyValues mpvs = null; List<PropertyValue> original; // 2.判断属性值列表的类型:将转换过的属性赋值到BeanWrapper的对应属性中,然后转为List集合,交给original // 它可能是MutablePropertyValues类型的,也可能是PropertyValues类型的 // 2.1 如果是MutablePropertyValues类型的,则将转换过的属性列表直接set到BeanWrapper中,然后将属性值列表转换为List集合 // 2.2 如果不是,则将属性值列表转换为List集合 if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; // 如果属性值列表已经被转换过,将其直接set到BeanWrapper中 if (mpvs.isConverted()) { // Shortcut: use the pre-converted values as-is. try { bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } original = mpvs.getPropertyValueList(); } else { // 如果不是,则将属性值列表转换为List集合,交给original original = Arrays.asList(pvs.getPropertyValues()); } // 获取自定义类型转换器 TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } // 创建一个BeanDefinitionValueResolver对象 // 用于解析属性值。该对象接收当前的 BeanDefinition 对象、bean 的名称、自定义的类型转换器作为参数 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // 创建一个深拷贝列表deepCopy,用于存储解析转换过的属性 List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; // 3.遍历属性值列表:如果每个属性转换过则直接加入deepCopy中,如果没转换过则将属性解析、转换后加入deepCopy // 每一个属性值都是一个键值对 for (PropertyValue pv : original) { if (pv.isConverted()) { // 如果属性值已经被转换过,直接保存 deepCopy.add(pv); } else { // 如果没转换过 // 获取键值对 String propertyName = pv.getName(); Object originalValue = pv.getValue(); // 判断该属性是否是自动装配的标记 if (originalValue == AutowiredPropertyMarker.INSTANCE) { // 获取该方法的写方法(setter方法) Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod(); // 非空校验这个写方法 if (writeMethod == null) { throw new IllegalArgumentException("Autowire marker for property without write method: " + pv); } // 将属性值替换为一个新的DependencyDescriptor对象,该对象表示对属性的依赖描述 originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true); } // 解析该对象的属性值 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); // 创建convertedValue,保存解析后的属性值,默认就是解析值 Object convertedValue = resolvedValue; // 判断属性是否可转换,并且不是嵌套或索引属性。 boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { // 如果属性可转换,将解析后的属性值进行类型转换。 convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // 可能将转换后的值存储在合并的bean定义中,以避免对每个创建的bean实例进行重新转换。 if (resolvedValue == originalValue) { // 如果解析后的值与原值相同 if (convertible) { // 如果该属性可转换 // 保存转换后的值进入pv pv.setConvertedValue(convertedValue); } // 将pv存入深拷贝数组 deepCopy.add(pv); } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { // 如果属性可转换且原始值是 TypedStringValue 类型且不是动态值,并且转换后的值不是集合或数组类型, // 则保存转换后的属性值,保存到深拷贝列表 pv.setConvertedValue(convertedValue); deepCopy.add(pv); } else { // 标记需要解析,然后存到深拷贝列表 resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } // 如果mpvs不为空,且不需要解析,则标记为已转换 if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // 4.将解析后的深拷贝列表set到BeanWrapper中 try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
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 定义中的属性值。
具体功能:
- 解析属性值是否需要引用其他 Bean 或 Bean 名称,并进行相应的解析。对应方法resolveValueIfNecessary()、resolveReference();
- 解析包含的内部 Bean。对应方法resolveInnerBean();
- 解析数组、列表、集合、映射、属性等特殊类型的属性值。对应方法resolveManagedList()等;
- 将属性值转换为目标类型。对应方法resolveTargetType()等;
4.4.5 resolveReference():调用getBean()解析属性为Bean
上面 resolveValueIfNecessary()方法调用了resolveReference()方法,对属性进行解析。
本方法主要调用了getBean()方法,注册属性为Bean,然后获取到这个Bean。
核心流程:
- 获取Bean名:获取运行时 Bean 引用的名称。
- 获取Bean:根据引用的名称,调用
getBean()
方法从 BeanFactory 中获取对应的 Bean 实例。 - 空值校验、异常处理:如果没有获取到Bean返回空,如果有异常,加上错误信息并抛出异常;
详细流程:
org.springframework.beans.factory.support.BeanDefinitionValueResolver
/** * 在该方法中,会为当前初始化bean主要为属性注入另外一个bean,调用getBean()方法获取需要注入的bean,最终注入到属性中 */ private Object resolveReference(Object argName, RuntimeBeanReference ref) { try { Object bean; String refName = ref.getBeanName(); refName = String.valueOf(doEvaluate(refName)); if (ref.isToParent()) { if (this.beanFactory.getParentBeanFactory() == null) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Can't resolve reference to bean '" + refName + "' in parent factory: no parent factory available"); } bean = this.beanFactory.getParentBeanFactory().getBean(refName); } else { // 当前初始化bean主要为属性注入另外一个bean,调用getBean()方法获取需要注入的bean,最终注入到属性中 bean = this.beanFactory.getBean(refName); this.beanFactory.registerDependentBean(refName, this.beanName); } if (bean instanceof NullBean) { bean = null; } return bean; } catch (BeansException ex) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex); } }
4.4.6 属性获取Bean流程:getBean() -> doGetBean()
4.4.6.1 直接从缓存中获取到AService
上面方法解析Bean的时候,调用了getBean()方法。
你可能在想,这不是无限套娃了吗?先调用getBean()获取AService,获取过程中,又调用getBean()获取属性BService,然后又调用getBean()获取AService属性,无限循环。
详细Bean加载流程参考:
事实不是这样的。
这次执行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,代表允许循环依赖
@Override @Nullable public Object getSingleton(String beanName) { return getSingleton(beanName, true); }
4.4.6.3 getSingleton(beanName,true):从缓存中获取单例Bean(是否允许循环依赖)
核心逻辑:
- 尝试从一级缓存中获取;
- 判断循环依赖:如果从一级缓存没取到,并且发生了循环依赖,则加锁执行下面逻辑:
- 尝试从二级缓存中获取;
- 从三级缓存中获取:如果获取到则执行Lambda表达式,生成提前代理对象,然后将其从三级缓存删除、存入二级缓存并返回;
提前代理对象:
提前代理对象是这一步执行第三级缓存的value,即一个Lambda表达式生成的(具体的实参参考上文的“存入第三级缓存”),因为这个对象还不是经历完整生命周期的Bean,还没有被IOC容器管理,只是用于解决循环依赖问题,所以称他为“提前代理对象”。
详细代码:
protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 从一级缓存获取BeanName对应的单例对象 Object singletonObject = this.singletonObjects.get(beanName); // 如果没有获取到,但是当前 BeanName对应的单例对象又处于创建中 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 从二级缓存中获取当前BeanName对应的单例对象 singletonObject = this.earlySingletonObjects.get(beanName); // 二级缓存中没有,但是allowEarlyReference为true,在doCreateBean方法中已经设置,所以这里为true if (singletonObject == null && allowEarlyReference) { // 从三级缓存中获取 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 这里就是三级缓存函数方法,同过Factory创建一个单例对象 singletonObject = singletonFactory.getObject(); // 添加到二级缓存中,半成品对象 this.earlySingletonObjects.put(beanName, singletonObject); // 同时删除三级缓存 this.singletonFactories.remove(beanName); } } } } // 返回当前半成品对象 return singletonObject; }
4.4.6.4 回顾doGetBean():getBean()的核心逻辑处理方法
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。
流程概述:
- 提取beanName;
- 尝试从缓存获取Bean:调用getSingleton(String beanName),如果当前Bean已经被加载过获取因为循环依赖正咋被加载,这里将直接获取到Bean实例;
- 循环依赖的判断。
- 递归去父容器获取Bean实例。
- 从当前容器获取BeanDefinition实例。
- 递归实例化显式依赖的Bean。
- 根据不同的Scope采用不同的策略创建Bean实例:调用getSingleton(String beanName, ObjectFactory<?> singletonFactory),传参Lambda表达式中有createBean()去创建Bean。
- 对Bean进行类型检查。
流程详解:
org.springframework.beans.factory.support.AbstractBeanFactory
protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // 1. 提取出对应的beanName。 // 将参数name(1.FactoryBean要去掉前缀&,2.别名A指向B的Bean要转成B)转换成容器中真实的bean名称(获取容器中真实beanName) String beanName = transformedBeanName(name); Object bean; // 2.尝试直接从三级缓存中获取Bean // 尝试从一级缓存中获取之前被实例化过了的单例bean或从三级缓存中获取ObjectFactory,执行Lambda表达式创建单例Bean。 // 如果当前Bean已经被加载过,或者因为循环依赖处在加载中,就可以直接从这个getSingleton(beanName)中获取到Bean, // 否则就要执行后面第8步的getSingleton(beanName,包含createBean的Lambda) Object sharedInstance = getSingleton(beanName); // 如果之前已经创建过该单例bean,并且args为空(单例 bean不可以用这个args,它是为多例设计的) if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { // 如果Bean还在创建中,则说明是循环依赖. if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } // 3. 检测处理FactoryBean类型的bean并返回实例。 // 如果是普通的bean,直接返回,如果是factoryBean,则返回它的getObject. 这一步主要还是针对FactoryBean的处理。 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } // 如果scope->prototype,singleton.但是在缓存中无法找到 else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. // 4. 先根据缓存判断一下当前的bean是否正在被创建,如果是的话表示依赖循环了;只有单例情况才会尝试解决循环依赖,原型模式直接抛出异常。因为原型模式无法解决循环依赖问题。 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. // 5. 获取父级的BeanFactory BeanFactory parentBeanFactory = getParentBeanFactory(); // 如果在当前容器中无法找到指定名称的bean,此时递归去parentFactory查找. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. // 递归到BeanFactory中检测,针对FactoryBean,将Bean的&重新拼上 String nameToLookup = originalBeanName(name); // 如果parentBeanFactory属于AbstractBeanFactory实例 if (parentBeanFactory instanceof AbstractBeanFactory) { // 递归查找 return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. // 如果有参数,则委派父级容器根据指定名称和显式的参数查找. return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. // 如果没有参数,委托父级容器根据指定名称和type进行查找 return parentBeanFactory.getBean(nameToLookup, requiredType); } } // 如果当前要获取的bean只是为了进行类型检查就标记bean已经被创建 if (!typeCheckOnly) { // 这里是将 当前创建的beanName 保存到 alreadyCreated 集合中。alreadyCreated 中的bean表示当前bean已经创建了,在进行循环依赖判断的时候会使用 markBeanAsCreated(beanName); } try { // 6. 将当前 beanName 的 BeanDefinition 和父类BeanDefinition 属性进行一个整合 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 对合并的BeanDefiniton进行检测,主要判断是否为abstract. checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. // 7. 寻找bean的依赖 // 获取当前Bean所有依赖的Bean名称 String[] dependsOn = mbd.getDependsOn(); // 如果需要依赖,则递归实例化依赖bean if (dependsOn != null) { for (String dep : dependsOn) { // 判断是否有循环依赖的情况 : A依赖B,B依赖A if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 注册依赖信息,将依赖信息保存到 dependentBeanMap、dependenciesForBeanMap中 registerDependentBean(dep, beanName); try { // 获取依赖的bean,这一步又回到了最初的getBean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. // 8 针对不同的Scope 进行bean的创建 // 实例化依赖的bean便可以实例化mdb本身了 // 如果BeanDefiniton为单例 if (mbd.isSingleton()) { // 匿名内部类,创建Bean实例对象,并且注册给所依赖的对象 // 关键方法:单例类实例化的入口 sharedInstance = getSingleton(beanName, () -> { try { // 创建单例bean的入口. // =============关键=============== return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. // 显性从单例缓存中删除bean实例. // 因为单例模式下为了解决循环依赖,可能留有残余的信息,此处进行销毁 destroySingleton(beanName); throw ex; } }); // 解决FactoryBean的问题 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. // 原型模式的回调 // 如果是原型模式,创建一个实例,在原型模式下,每次getBean都会产生一个新的实例 Object prototypeInstance = null; try { // 保存当前线程正在创建的beanName 到 prototypesCurrentlyInCreation 中 beforePrototypeCreation(beanName); // 直接创建bean prototypeInstance = createBean(beanName, mbd, args); } finally { // 完成创建后,从 prototypesCurrentlyInCreation 中移除当前线程正在创建的beanName afterPrototypeCreation(beanName); } // 解决FactoryBean的问题 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { // 指定scope上实例化bean String scopeName = mbd.getScope(); if (!StringUtils.hasLength(scopeName)) { throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'"); } Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { // 保存当前线程正在创建的beanName 到 prototypesCurrentlyInCreation 中 beforePrototypeCreation(beanName); try { // 创建bean return createBean(beanName, mbd, args); } finally { // 移除当前线程正在创建的beanName 从 prototypesCurrentlyInCreation 中 afterPrototypeCreation(beanName); } }); // 解决FactoryBean的问题 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // Check if required type matches the type of the actual bean instance. // 9 类型转换 // 检查需要的类型是否符合bean 的实际类型 if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
4.5 doCreateBean的其他逻辑
在属性填充后,AService将执行doCreateBean()剩余的逻辑,即AOP增强、校验依赖注册、注册销毁Bean,也就是下面流程中的6,7,8,执行完后,这个Bean以及它的依赖都已经注册完毕:
- 判断单例:创建一个BeanWrapper,如果是单例,则取出缓存赋值给它,并清除缓存
- wrapper为空时实例化Bean:调用createBeanInstance()方法,默认用无参构造方法实例化Bean,赋值给wrapper
- 合并处理BeanDefinition:应用所有已注册的 MergedBeanDefinitionPostProcessor (用于修改或扩展BeanDefinition)到给定的 BeanDefinition 实例
- 放进三级缓存:当Bean是单例、允许循环依赖时,将Lambda表达式放进三级缓存,以后如果执行这个Lambda表达式,生成的将是BService的提前代理对象;
- 属性填充:填充注解@Autowired、@Resource、@Value等的属性
- 初始化bean:调用initializeBean()方法,初始化和aop,通过JDK的Proxy.newProxyInstance()实现动态代理,返回目标对象的代理对象,对Bean进行增强。
- 执行所有BeanPostProcessor的初始化前方法:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessBeforeInitialization()方法。本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。
- 初始化:如果Bean实例实现了InitializingBean接口(通过instanceof判断),调用Bean重写的afterPropertiesSet()方法,处理初始化逻辑。afterPropertiesSet译为“在属性填充之后”
- 执行所有BeanPostProcessor的初始化后方法:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessAfterInitialization()方法。本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。
- 校验依赖注册为Bean:获取所有注入属性,检查这些属性是否已被注册为Bean,如果存在依赖没注册为Bean,则抛出异常
- 注册销毁Bean:调用registerDisposableBeanIfNecessary()方法,注册DisposableBean,以便在销毁bean 的时候可以运行指定的相关业务。
- 判断实现DisposableBean接口:当前Bean是否实现了DisposableBean接口,是则直接返回true;否则进行【推断销毁方法】流程
- 推断销毁方法:
- 寻找当前bean下是否有close方法或者shutdown方法,或者是否实现了AutoCloseable接口,是则直接返回销毁方法名称
- 感知销毁Bean后置处理器:如果【推断销毁方法】也没有结果,则调用【感知销毁Bean后置处理器】DestructionAwareBeanPostProcessor.requiresDestruction(bean)判断,如果当前bean是ApplicationListener子类需要销毁,拥有@PreDestroy注解了的方法就是需要销毁
- 适配成DisposableBeanAdapter对象:如果需要销毁,则适配成DisposableBeanAdapter对象,并存入disposableBeans中(一个LinkedHashMap<String, Object>)
详细解析:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
/** * 创建Bean的核心逻辑处理方法 * * @param beanName bean名称 * @param mbd BeanDefinition对象 * @param args 构造函数参数 * @return {@link Object} * @throws BeanCreationException Bean创建异常 */ protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 1.判断单例:创建一个BeanWrapper,如果是单例,则取出缓存赋值给它,并清除缓存 BeanWrapper instanceWrapper = null; // 如果BeanDefinition是单例模式,就先从缓存中清除 if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } // 2.wrapper为空时实例化Bean:调用createBeanInstance()方法,默认用无参构造方法实例化Bean,赋值给wrapper // bean初始化第一步:默认调用无参构造实例化Bean // 构造参数依赖注入,就是发生在这一步 if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } // 实例化后的Bean对象 final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { // 将 解析类型 设置 为 beanType mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. // 使用后置处理器 对其进行处理 synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { // 合并处理BeanDefinition:应用所有已注册的 MergedBeanDefinitionPostProcessor (用于修改或扩展BeanDefination)到给定的 BeanDefinition 实例 //对@Autowire,@Value等这些注解进行处理 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // 3.存入三级缓存:当Bean是单例、允许循环依赖时,将Lambda表达式放进三级缓存,以后如果执行这个Lambda表达式,生成的将是BService的提前代理对象; // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. /**是否需要提前曝光: 单例& 允许循环依赖 & 当前bean正在创建中, 检查循环依赖 这里主要是调用 方法addSingletonFactory ,往缓存singletonFactories里面 放入一个 ObjectFactory 当其他的bean 对该bean 有依赖时,可以提前获取到 getEarlyBeanReference方法就是获取一个引用, 里面主要是 调用了 SmartInstantiationAwareBeanPostProcessor, 的 getEarlyBeanReference 方法,以便解决循环依赖问题, 这里 一般都是bean 本身, 在 AOP时 是代理 **/ boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } // 将刚创建的bean放入三级缓存中,singleFactories(key是beanName,value是ObjectFactory) // 注意此处实参又是一个lambda表达式, // 即参数传入的是ObjectFactory类型一个匿名内部类对象,在后续再缓存中查找Bean时会触发匿名内部类getEarlyBeanReference()方法回调 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // 4.依赖处理 // Initialize the bean instance. Object exposedObject = bean; // 下面就是初始化实例了 try { // 5.填充属性(DI依赖注入发生在此步骤) // 对bean进行填充,将各个属性值注入,其中可能存在依赖于其他bean的属性,会递归初始化 populateBean(beanName, mbd, instanceWrapper); // 6.初始化bean:初始化和aop,通过JDK的Proxy.newProxyInstance()实现动态代理,返回目标对象的代理对象,对Bean进行增强。 // AOP是通过自动代理创建器AbstractAutoProxyCreator的postProcessAfterInitialization() //方法的执行进行代理对象的创建的,AbstractAutoProxyCreator是BeanPostProcessor接口的实现类 //进一步初始化Bean //注入 Aware 相关的对象 // 调用 后置处理器 BeanPostProcessor 里面的postProcessBeforeInitialization方法 // 调用 initialzingBean,调用实现的 afterPropertiesSet() // 调用 init-mothod,调用相应的init方法 // 调用 后置处理器 BeanPostProcessor 里面的调用实现的postProcessAfterInitialization方法 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); // earlySingletonReference 只有在检测到有循环依赖的情况下才会不为空 if (earlySingletonReference != null) { //如果exposedObject 没有在初始化方法中被改变,也就是没有被增强 if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { // 7.依赖检查:获取所有注入属性,检查这些属性是否已被注册为Bean String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); // 检查依赖 for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } /** 因为 bean 创建后其所依赖的bean一定是已经创建, actualDependentBeans 不为空则表示 当前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 " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } // 8.注册销毁Bean try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }