Spring源码学习--bean加载步骤

之前博客的内容包括xml的加载,bean的解析和注册以及用户自定义标签的解析和注册都是容器初始化的内容.bean的加载时在这个基础上进行的,bean的加载过程比较复杂,设计的代码量很多.所以准备将bean的加载过程分为多个部分进行讲解.今天主要讲解bean的加载大致流程,之后会对每个步骤再进行细化讲解.

bean的加载的入口是通过调用工厂方法的getBean()开始.如下面代码所示:

1
2
3
XmlBeanFactory bf = new XmlBeanFactory("bean.xml");
//正式启动bean的加载
MyTestBean bean = (MyTestBean)bf.getBean("myTestBean");

根据spring的习惯,一般将正式执行代码放在以do开头的方法里.getBean()内部的实现也是如此,是通过调用doGetBean()方法.代码如下:

1
2
3
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

getBean()和doGetBean的代码是在AbstractBeanFactory实现的.doGetBean的方法有些长,这里涵盖了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
191
192
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//提取对应的name
//传入的name可能是别名,所以需要做一个转化
final String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
/*
* 检查缓存中或实例工厂中是否有对应的实例
* 为什么首先会使用这个方法?
* 因为在创建单例bean的时候会存在依赖注入的情况.而在创建依赖的时候为了避免循环依赖.
* spring 创建bean的原型时不等bean创建完成就将创建bean的ObjectFactory提早曝光
* 也就是将ObjectFactory加入到缓冲中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory.
*/
//直接从缓存或singletonFactories中的ObjectFactory获取
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 + "'");
}
}
//返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身,所以这里进行处理返回实例本身.
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
//只有在单例情况下才会尝试解决循环依赖,原型情况下,如果存在
//A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候
//因为对B的创建再次返回创建A,造成循环依赖,也就是下面的情况.

// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//查看当前原型的bean是否正在创建中,即引起循环引用.
//这里只是直接把正在创建中的对象考虑为发生循环引用,没有考虑多线程情况下两个线程同时去获取bean.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果beanDefinitionMap 中 也就是在所有已经加载的类中不包括beanName则尝试从parentBeanFactory中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
//递归到 BeanFactory中寻找
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//真实目的是?
//如果不是仅仅做类型检查则创建bean,这里要进行记录.
if (!typeCheckOnly) {
//标记为已经创建了
markBeanAsCreated(beanName);
}

try {
//将存储xml配置文件的GenericBeanDefinition转换为RootBeanDefinition,
//如果制定BeanName是子Bean的话同时会合并父类的相关属性.
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// Guarantee initialization of beans that the current bean depends on.
//获得所有依赖
String[] dependsOn = mbd.getDependsOn();
//如果存在依赖,则需要递归实例化依赖的bean.找的是beanName所依赖的其他bean. 递归获取
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
//如果 dependsOnBean 又依赖于beanName,则形成循环依赖关系.
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
//缓存依赖调用 注册依赖关系
registerDependentBean(dependsOnBean, beanName);
//递归的加载bean, 这里的依赖不是属性依赖,
//是某个类的创建必须在某些类完成创建之后进行.这个是属性中配置的depends-on 属性
getBean(dependsOnBean);
}
}
//实例化依赖的bean 后便可以实例化mbd本身了.(即先把依赖的bean都实例化了,再来实例化本身)
// Create bean instance.
//singleton模式
if (mbd.isSingleton()) {
//如果注册表里没有该单例,则用这里定义的工厂创建单例
//为何要先创建一个工厂呢?  暂时的理解是可以提前暴露工厂然后生成对象,同时提高代码的封装性
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
//留给子类实现
//AbstractAutowireCapableBeanFactory
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.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
//prototyp模式的创建(直接新建一个实例)
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
//说明正在创建,加入正在创建队列中
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//说明创建完成.从正在创建表移走
afterPrototypeCreation(beanName);
}
//回去bean对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
//指定scope的 
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
//从scope范围的缓存中获取实例,如果没有则使用这里定义的工厂创建
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
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的实际类型
// Check if required type matches the type of the actual bean instance.
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的加载大致过程都能理解.限制我们结合以上代码总结bean加载的大致步骤:

  1. 首先将beanName进行转化,这里转化的目的是将别名转化为具体的beanName. 因为spring里提供了别名的支持,用户在调用bean的时候可能调用的不是真实的beanName,而是调用别名.就像你朋友叫你时不一定都叫你名字,可能叫你外号,如小胖等.所以需要将外号转化为真实名字,spring里的名字转化做的也是这个工作.
  2. 尝试从缓冲或实例工厂中获取bean.该步骤主要时解决单例中的循环依赖问题.为了解决该问题,spring在创建bean的时候不等bean真正创建完成时将生成这个bean的ObjectFactory提前曝光,即保存到缓存中.一旦下一个bean的创建依赖当前bean时直接使用ObjectFacory.
  3. 如果缓冲中获取的bean不为空,那么指定bean的实例化. 因为缓冲中保存的bean是原始状态,不一定时我们想要的,所以这步骤主要是将缓冲中原始状态转化为最终想要的bean. 例如,缓冲中可能放的是生成bean的工厂,这时需要调用工厂方法生成对应的bean.
  4. 如果第二步从缓冲中取得的bean是空的,那进行真正的加载过程.首先判断该bean是否时原型并且是否存在循环依赖问题.
      spring只为用户解决单例情况下的属性注入的循环依赖问题,对于其他循环依赖只能抛出异常.这些循环依赖包括原型循环依赖,单例情况下的构造器形成的循环依赖问题等.
  5. 如果当前容器中不包含该bean,并且存在父工厂,则从父工厂中去加载.
  6. 将存储xml配置文件的GenericBeanDefinition转换为RootBeanDefinition,因为后续的处理都是针对RootBeanDefinition.
  7. 完成其所有依赖bean的加载.
  8. 针对不同的scope创建bean
  9. 最后进行类型转换,将bean转换为requireType所指定的类型.
0%