Spring加载Bean确实很复杂,估计要看几遍才能摸清楚脉络,分析这一块源码大大小小耗费了好多天,终于耐着性子简单的分析完了。
写这个总结还得拉出一段代码:

1
2
3
4
5
6
7
8
9
10
11
//资源定位
ClassPathResource resource = new ClassPathResource("bean.xml");
//bean工厂
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//xml BeanDefinition 阅读器
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
//加载与注册BeanDefinition,完成后的BeanDefinition放置在IOC容器中。
reader.loadBeanDefinitions(resource);

//bean的加载
Object bean = factory.getBean("xxx");

即最后一行bean的加载逻辑,通过DefaultListableBeanFactory的getBean()方法,
最终调用到AbstractBeanFactory的doGetBean(final String name, @Nullable final Class requiredType,@Nullable final Object[] args, boolean typeCheckOnly)主流程。

  1. 从缓存中获取原始bean实例
  2. 创建原始bean实例
    1. 获取BeanWrepper
    2. 属性填充
    3. 初始化bean
  3. 从原始bean实例中获取我们需要的对象
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
//返回指定bean的一个实例,该实例可以是共享的,也可以是独立的。
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

// 返回bean名称,在必要时去掉工厂的取消引用前缀,并将别名解析为规范名称。
final String beanName = transformedBeanName(name);
// 最终返回的bean
Object bean;

// 检查单例缓存中手动注册的单例。
Object sharedInstance = getSingleton(beanName);

//单例缓存中存在这个bean
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
//指定的单例bean当前是否正在创建(在整个工厂内)。
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//获取给定bean实例的对象,对于FactoryBean,要么是bean实例本身,要么是它创建的对象。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//单例缓存中不存在这个bean
else {
//假设我们在一个循环引用中,如果我们已经创建了这个bean实例,则会失败:
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// 获取父bean工厂,其用于bean继承支持。
BeanFactory parentBeanFactory = getParentBeanFactory();
// 检查这个工厂中是否存在bean定义。
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 未找到->检查父类。
//确定原始bean名称,将本地定义的别名解析为规范名称。
String nameToLookup = originalBeanName(name);
//如果父bean工厂instanceof AbstractBeanFactory
if (parentBeanFactory instanceof AbstractBeanFactory) {
//从父工厂中获取bean
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// 使用显式args委托给父对象。
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// 没有args ->委托给标准getBean方法。
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
//以上条件都不满足,直接根据要检索的bean的名称获取
return (T) parentBeanFactory.getBean(nameToLookup);
}
}

// 如果不是仅仅做类型检查则是创建bean,这里需要记录
if (!typeCheckOnly) {
//将指定的bean标记为已经创建(或即将创建)。
markBeanAsCreated(beanName);
}

try {
// 从容器中获取 beanName 相应的 GenericBeanDefinition,并将其转换为 RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

//检查给定的合并bean定义,可能会引发验证异常。
checkMergedBeanDefinition(mbd, beanName, args);

// 保证当前bean所依赖的bean的初始化。
// 返回此bean所依赖的bean名称。
String[] dependsOn = mbd.getDependsOn();
// 如果有依赖
if (dependsOn != null) {
for (String dep : dependsOn) {
//确定指定的依赖bean是否已注册为依赖于给定bean或依赖于其传递依赖项。
//循环依赖的情况
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//为给定bean注册一个依赖bean,在销毁给定bean之前销毁它。
registerDependentBean(dep, beanName);
try {
//获取依赖bean
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

//创建bean实例。
//判断scope是不是"singleton",如果scope为空,也走单例模式。
if (mbd.isSingleton()) {
//返回在给定名称下注册的(原始)单例对象,如果还没有注册,则创建并注册一个新的单例对象。
sharedInstance = getSingleton(beanName, () -> {
try {
//为给定的合并bean定义(和参数)创建bean实例。
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// 显式地从单例缓存中删除实例: 它可能是在创建过程中急切地放在那里的,以允许循环引用解析。
//还要删除接收到该bean的临时引用的任何bean
destroySingleton(beanName);
throw ex;
}
});
//获取给定bean实例的对象,对于FactoryBean,要么是bean实例本身,要么是它创建的对象。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//判断scope是否为"prototype"
else if (mbd.isPrototype()) {
// 它是一个原型——>创建一个新实例。
Object prototypeInstance = null;
try {
//原型创建之前的回调。
//默认实现将原型注册为当前正在创建的状态。
beforePrototypeCreation(beanName);
//为给定的合并bean定义(和参数)创建bean实例。
prototypeInstance = createBean(beanName, mbd, args);
} finally {
//原型创建后的回调。
//默认实现将原型标记为不在创建中。
afterPrototypeCreation(beanName);
}
//获取给定bean实例的对象,对于FactoryBean,要么是bean实例本身,要么是它创建的对象。
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//request/session/globalsession
else {
String scopeName = mbd.getScope();
//获取 scope 缓存
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// scope 缓存中获取对象
Object scopedInstance = scope.get(beanName, () -> {
//原型创建之前的回调。
//默认实现将原型注册为当前正在创建的状态。
beforePrototypeCreation(beanName);
try {
//为给定的合并bean定义(和参数)创建bean实例。
return createBean(beanName, mbd, args);
} finally {
//原型创建后的回调。
//默认实现将原型标记为不在创建中。
afterPrototypeCreation(beanName);
}
});
//获取给定bean实例的对象,对于FactoryBean,要么是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) {
//在bean创建失败后,对缓存的元数据执行适当的清理。
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}

// 检查所需类型是否与实际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.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
// 返回bean
return (T) bean;
}

1、从缓存中获取原始bean实例

getSingleton(String beanName),只有单例模式才会从缓存中获取原始bean实例。

2、创建原始bean实例

如果缓存没有,也没有parentBeanFactory,则调用createBean(beanName, mbd, args)方法获取,最终会调用doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)方法。
这就是巨无霸了!!方法主要分了三个大部分:首先通过createBeanInstance(beanName, mbd, args)方法,获取BeanWrepper;之后将属性填充到BeanWrapper,最后初始化bean。
具体源码分析可以参考系列文章。

3、从原始bean实例中获取我们需要的对象

获取的原始bean对象是不能直接返回的,需要最后通过getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd)
方法处理一下,这个方法我在以前也分析过了。

感慨一下,Spring加载Bean的逻辑代码的体量真的好大,来来回回看了好久,总算结束,虽然对其内部还是一知半解,但是明显的比以前的认知好多了,总的来说收获很大,记住要静下心来,硬看。

tencent.jpg