Spring源码全家桶

根据之前所看的视频和博客,再一次对 Spring 源码进行整理与分析

核心架构

image.png

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
/**
* 容器初始化的过程:BeanDefinition 的 Resource 定位、BeanDefinition 的载入、BeanDefinition 的注册。
* BeanDefinition 的载入和 bean 的依赖注入是两个独立的过程,依赖注入一般发生在 应用第一次通过
* getBean() 方法从容器获取 bean 时。
*
* 另外需要注意的是,IoC 容器有一个预实例化的配置(即,将 AbstractBeanDefinition 中的 lazyInit 属性
* 设为 true),使用户可以对容器的初始化过程做一个微小的调控,lazyInit 设为 false 的 bean
* 将在容器初始化时进行依赖注入,而不会等到 getBean() 方法调用时才进行
*/
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 调用容器准备刷新,获取容器的当前时间,同时给容器设置同步标识
prepareRefresh();

// 告诉子类启动 refreshBeanFactory() 方法,BeanDefinition 资源文件的载入从子类的 refreshBeanFactory() 方法启动开始(注解方式的这里跳过了)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 为 BeanFactory 配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);

try {
// 为容器的某些子类指定特殊的 BeanPost 事件处理器
postProcessBeanFactory(beanFactory);

// 调用所有注册的 BeanFactoryPostProcessor 的 Bean
invokeBeanFactoryPostProcessors(beanFactory);

// 为 BeanFactory 注册 BeanPost 事件处理器.
// BeanPostProcessor 是 Bean 后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);

// 初始化信息源,和国际化相关.
initMessageSource();

// 初始化容器事件传播器
initApplicationEventMulticaster();

// 调用子类的某些特殊 Bean 初始化方法
onRefresh();

// 为事件传播器注册事件监听器.
registerListeners();

// 初始化 Bean,并对 lazy-init 属性进行处理(这里是初始化自己使用的Bean)
finishBeanFactoryInitialization(beanFactory);

// 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}

catch (BeansException ex) {
// 销毁以创建的单态 Bean
destroyBeans();

// 取消 refresh 操作,重置容器的同步标识.
cancelRefresh(ex);

throw ex;
}
}
}

初始必备宝典

DefaultListableBeanFactory:IOC 容器 存储的所有 BeanDefinition bean 的信息

类图

BeanFactory

image

BeanDifinition

image

IOC 全家桶

容器中除了有我们自己定义的 Bean,还有 Spring 官方用来解析我们 Bean 的后置处理器和其他。这里我们主要看我们自己定义的 Bean 是怎么初始化和创建的。

在前面十二大步的finishBeanFactoryInitialization中进行我们 Bean 的初始化

直接调用到了 getBean()

image.png加载 Beandefinition

todo

如何创建出一个 Bean/依赖注入原理

核心方法:getBean()

getBean 方法直接调用了 doGetBean 方法 

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// 真正实现向 IoC容器 获取 bean 的功能,也是触发 依赖注入(DI) 的地方
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args,
boolean typeCheckOnly) throws BeansException {

// 根据用户给定的名称(也可能是别名alias) 获取 IoC容器 中与 BeanDefinition 唯一对应的 beanName
final String beanName = transformedBeanName(name);
Object bean;

// 根据 beanName 查看缓存中是否有已实例化的 单例bean,对于 单例bean,整个 IoC容器 只创建一次
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
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 + "'");
}
}
// 获取给定 bean 的实例对象,主要是完成 FactoryBean 的相关处理
// 注意:BeanFactory 是一个 IoC容器,它保存了 bean 的基本配置信息。
// 而 FactoryBean 是 IoC容器 中一种特殊的 bean,它能够实例化 bean对象,注意两者之间的区别
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 如果应用程序要获取的 bean 还未创建
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// 获取当前容器的父容器
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果当前容器中没有指定的 bean,且当前容器的父容器不为空
// 则从父容器中去找,如果父容器也没有,则沿着当前容器的继承体系一直向上查找
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 根据用户传入的 name(有可能是别名alias),获取唯一标识的 beanName
String nameToLookup = originalBeanName(name);
if (args != null) {
// 委派父级容器根据指定名称和显式的参数查找
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 委派父容器根据指定名称和类型查找
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}

// 创建的 bean 是否需要进行类型验证,一般不需要
if (!typeCheckOnly) {
// 向容器标记指定的 bean 已经被创建
markBeanAsCreated(beanName);
}

try {
// 根据 beanName 获取对应的 RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// 获取当前 bean 所依赖bean 的 beanName,下面的 getBean(dependsOnBean) 方法会触发
// getBean() 的递归调用,直到取到一个不依赖任何其它 bean 的 bean 为止。
// 比如:beanA 依赖了 beanB,而 beanB 依赖了 beanC,那么在实例化 beanA 时会先实例化
// beanC,然后实例化 beanB 并将 beanC 注入进去,最后实例化 beanA 时将 beanB 注入
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
// 递归调用 getBean() 方法,从末级节点依次实例化 依赖的bean
getBean(dependsOnBean);
// 把 当前bean 直接依赖的bean 进行注册
//(也就是通过 setter 或构造方法将依赖的 bean 赋值给当前 bean 对应的属性)
registerDependentBean(dependsOnBean, beanName);
}
}

// 如果当前 bean 是单例的
if (mbd.isSingleton()) {
// 这里使用了一个匿名内部类,创建 bean实例对象
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
// 根据给定的 beanName 及 RootBeanDefinition对象,创建 bean 实例对象
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
// 获取给定 bean 的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

// 创建原型模式的 bean 实例对象
else if (mbd.isPrototype()) {
// 原型模式 (Prototype) 每次都会创建一个新的对象
Object prototypeInstance = null;
try {
// 回调 beforePrototypeCreation() 方法,默认的功能是注册当前创建的原型对象
beforePrototypeCreation(beanName);
// 创建指定 bean 对象实例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 回调 afterPrototypeCreation() 方法,默认的功能是告诉 IoC容器
// 指定 bean 的原型对象不再创建了
afterPrototypeCreation(beanName);
}
// 获取给定 bean 的实例对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

// 要创建的 bean 既不是单例模式,也不是原型模式,则根据该 bean元素 在配置文件中
// 配置的生命周期范围,选择实例化 bean 的合适方法,这种在 Web 应用程序中
// 比较常用,如:request、session、application 等的生命周期
else {
// 获取此 bean 生命周期的范围
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
// bean 定义资源中没有配置生命周期范围,则该 bean 的配置不合法
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
// 这里又使用了一个 ObjectFactory 的匿名内部类,获取一个指定生命周期范围的实例
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
// 获取给定 bean 的实例对象
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;
}
}

// 对要返回的 bean实例对象 进行非空验证和类型检查,如果没问题就返回这个已经完成 依赖注入的bean
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
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;
}
}

流程分析

创建Bean.drawio.png

  1.  在 doGetBean 方法中,首先就是getSingleton 看能不能获取到实例对象

    1. 在这个方法中就是根据三级缓存中进行获取 Bean
  2. 如果没有获取到就走创建 Bean 的流程

    1. 有个检查原型 Bean 循环依赖的代码(跳过)if (isPrototypeCurrentlyInCreation(beanName))

     

  3. 标记 Bean 正在创建markBeanAsCreated(beanName)

  4. 检查依赖的 Bean(dependsOn) 递归调用来创建

  5. 创建单例 Bean

    1. 调用getSingleton 并传入创建 Bean 的工厂(第三级缓存)

    2. populateBean 自动注入

    3. initializeBean 初始化

ConfigurationClassPostProcessor 进行解析

在 populateBean 中进行依赖注入

三级缓存&&循环依赖问题与探析

其实一级缓存就能解决问题,但是为了不打破原本的设计(如 代理等这些后置处理器应当在初始化阶段完成)

Spring 为什么要用三级缓存来解决循环依赖(AOP),二级缓存不行吗_二级缓存能不能解决循环依赖-CSDN博客

  1.  一级缓存(Singleton Objects):这是一个存储完全初始化好的bean的缓存。当一个bean被完全处理并准备好后,它会被放入这个缓存中。

  2.  二级缓存(Early Singleton Objects):这个缓存存储的是早期暴露的对象,即还没有完全初始化的bean。这些对象已经被实例化,但可能还没有完成依赖注入和初始化。

  3.  三级缓存(Singleton Factories):这个缓存存储的是bean工厂对象,它允许在bean完全初始化之前对其进行引用和操纵。

image.png

用三级缓存的主要原因就是防止过快地进行动态代理(aop 需要)

因为每一个代理

附:

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
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}

启动步骤

Xml形式启动Bean容器:

// 告诉子类启动 refreshBeanFactory() 方法,BeanDefinition 资源文件的载入从子类的 refreshBeanFactory() 方法启动开始ConfigurableListableBeanFactory beanFactory =obtainFreshBeanFactory();

加载 BeanDefinition

ImportBeanDefinitionRegistrar


https://hexo-blog-five-swart.vercel.app/2024/10/27/Spring源码全家桶/
作者
方立
发布于
2024年10月27日
许可协议