前言
初始化Bean工厂 这个名字起的好像有点大,在前面创建了Bean工厂后填充了一些属性,创建了BeanDifinition但是一直没有注入Bean。
本章Bean就将正式入住了。
建议结合 “Bean的生命周期” 这个问题一起思考
抽象流程
源码流程

Bean 的生命周期
源码
BeanDefinition 的合并机制
在创建工厂并读取Bean配置时会创建一个
BeanDefinition
对象,BeanDefinition
是一个高级接口,准确来说时创建为了GenericBeanDefinition
。在经历合并后会变成
RootBeanDefinition
。虽然执行了
getMergedLocalBeanDefinition
方法,但是正常来说这不是真正的第一次合并。
BeanDefinition
什么时候合并的?在调用
BeanFactoryPostProcessor
时就已经执行了。1
2String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);在根据类型获取
postProcessorNames
时,遍历所有的BeanDefinitionName
获取合并后的BeanDefinition
1
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
为什么要这么做?
GenericBeanDefinition
相比较Root多了一个ParentName
的属性,用于记录Bean
的parent
参数。通过
GenericBeanDefinition
先定义好对象的父子关系,后面的RootBeanDefinition
根据前面所定义的父子关系去创建Bean
,没有父类直接创建,存在父类递归的去创建父类(父类也可能存在父类)。如果不提前创建父子关系,很有可能出现创建子类时发现父类还没有创建此时就需要大量的判断和查询显然是没有两阶段机制优雅
FactoryBean 处理机制
FactoryBean
和BeanFactory
看的很像,提供的服务也很像,但是底层时完全不同的。在 Spring 容器需要针对的做出一套处理机制/
1 | // 判断是否为FactoryBean |
[1] 根据(&+beanName)的规则来获取对象
FactoryBean
是一个特殊的Bean
!FactoryBean
是一个特殊的Bean
!FactoryBean
是一个特殊的Bean
!⚠️ 重要的事情说三遍,既然也是
Bean
也是需要交予Spring
容器管理的。正是因为FactoryBean
的特殊性,拥有了与其他Bean
不同BeanName
规则(需要前缀加一个&)[2] 急切的初始化
正常流程来说,
FactoryBean
的对象在初始阶段是不会被注入到Spring容器的,需要在getBean()
才会注入。如果
isEagerInit = true
就会立刻注入。⚠️ 此时注入的是实际的
Bean
,不是上面所注入的FactoryBean
[3] 普通的Bean
不是
FactoryBean
正常执行getBean()
即可1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# doGetBean
// 前面说了 FactoryBean 在BeanName起名有独特的规范
// 该方法就是去掉了&的前缀
String beanName = transformedBeanName(name);
Object bean;
// 提前检查单例缓存中是否有手动注册的单例对象,跟循环依赖有关联
Object sharedInstance = getSingleton(beanName);
// 如果bean的单例对象找到了,且没有创建bean实例时要使用的参数
if (sharedInstance != null && args == null) {
// ...省略部分源码
// 返回对象的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd){
// name 如果是&作为前缀
if (BeanFactoryUtils.isFactoryDereference(name)) {
// 如果beanInstance是NullBean实例
if (beanInstance instanceof NullBean) {
// 返回beanInstance
return beanInstance;
}
// 如果beanInstance不是FactoryBean实例
if (!(beanInstance instanceof FactoryBean)) {
// 抛出Bean不是一个Factory异常
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
// 如果mbd不为null
if (mbd != null) {
// 设置mbd是否是FactoryBean标记为true
mbd.isFactoryBean = true;
}
// 返回beanInstance
return beanInstance;
}
// 如果不是FactoryBean类型直接返回
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
// 定义为bean公开的对象,初始化为null
Object object = null;
// 如果mbd不为null
if (mbd != null) {
// 更新mbd的是否是FactoryBean标记为true
mbd.isFactoryBean = true;
}
else {
// 从FactoryBean获得的对象缓存集中获取beanName对应的Bean对象
object = getCachedObjectForFactoryBean(beanName);
}
// 如果object为null
if (object == null) {
// Return bean instance from factory.
// 从工厂返回Bean实例
// 将beanInstance强转为FactoryBean对象
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
// 如果是单例对象,则缓存从FactoryBean获得的对象、
// 如果mbd为null&&该BeanFactory包含beanName的BeanDefinition对象。
if (mbd == null && containsBeanDefinition(beanName)) {
//获取beanName合并后的本地RootBeanDefintiond对象
mbd = getMergedLocalBeanDefinition(beanName);
}
// 是否是'synthetic'标记:mbd不为null && 返回此bean定义是否是"synthetic"【一般是指只有AOP相关的prointCut配置或者
// Advice配置才会将 synthetic设置为true】
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 从BeanFactory对象中获取管理的对象.如果不是synthetic会对其对象进行该工厂的后置处理
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
// 返回为bean公开的对象
return object;
}getObjectForBeanInstance
方法可能出现三种情况:- 普通的Bean对象:直接返回
Instance
- 带有&符的FactoryBean:返回工厂Bean
- 不带&符的FactoryBean:返回对应工厂的实际Bean
- 普通的Bean对象:直接返回
Bean 是否正在创建中
1 | # doGetBean |
❗返回
True
表示当前Bean正在创建如果当前创建的Bean不为空且等于当前BeanName 或 当前正在创建的bean名称是Set集合,并包含该beanName
父工厂问题
通过BeanName获取Object时,如果存在父工厂且当前工厂不存在该BeanName时可能就嘀咕,它是不是存在父工厂了?
解决方案就是:通过递归的方式层层查找。
Bean存在依赖问题
例如在Xml定义Bean时可能设定一个 parent
属性:
1 | <bean id="student" class="com.lksun.debug.entity.Student"> |
student
作为monitor
的父类或者依赖对象,先有鸡还是先有蛋就很重要了。
必须先创建了依赖Bean再创建当前对象。
解决方法同样使用递归,获取当前对象是否有依赖对象,然后层层判断
解析Bean Class
1 | Class<?> resolvedClass = resolveBeanClass(mbd, beanName); |
获取到了Class对象后只需要一步resolvedClass.newInstance();
就可以获取到Object,但是Spring没有直接获取。
验证及准备覆盖的方法
todo ….
lookup-method replace-method
实际创建bean的方法 doCreateBean()
根据不同的策略创建Bean
1 | instanceWrapper = createBeanInstance(beanName, mbd, args); |
获取真实Bean对象
1 | Object bean = instanceWrapper.getWrappedInstance(); |
加入缓存
关于解决循环依赖相关的问题后续着重讲
1 | addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); |
判断一级缓存不存在当前Bean
然后执行:
1.将beanName,singletonFactory放到单例工厂的缓存(三级缓存)
2.在二级缓存删除当前Bean
3.将beanName添加已注册的单例集中
填充
1 | populateBean(beanName, mbd, instanceWrapper); |
执行初始化逻辑
1 | exposedObject = initializeBean(beanName, exposedObject, mbd); |
做了如下操作:
1.执行Aware接口处理器
2.BeanPostProcessor前置方法
3.调用初始化方法,先调用bean的InitializingBean接口方法,后调用bean的自定义初始化方法
4.BeanPostProcessor前置方法后置方法
注册Disposable
1 | // 注册bean对象,方便后续在容器销毁的时候销毁对象 |
标记为“未创建”
1 | // 创建单例后的回调,默认实现将单例标记为不在创建中 |
添加到一级缓存
等一切都完成后添加到一级缓存
1 | # getSingleton() |
1.先添加到一级缓存
2.在三级缓存移除
3.在二级缓存移除
4.保存到单例集合中
- 本文标题:Spring源码解析(四) 初始化Bean工厂
- 本文作者:SunRan
- 创建时间:2022-01-21 16:10:52
- 本文链接:https://lksun.cn/2022/01/21/Spring源码解析-四-初始化Bean工厂/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!