本文要看啥?

​ 前面已经了解了bean从配置文件到解析成BDHolder到注册的流程,我们已经将bean的信息封装好,塞入了map中,这个map可能在不同的实现里面,前面重点学的就是DefaultListableBeanFactory里的beanDefinitionMap.

​ 我们现在要探索bean的加载,围绕最初的示例代码:

1
MyTestBean bean =(MyTestBean)bf.getBean("myTestBean");

​ BeanFactory是个接口,其下实现关系很复杂, getBean方法的实现主要是在AbstractBeanFactory 这一层.

​ 本文就是先来快速体验一下加载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
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
//转换beanName
final String beanName = this.transformedBeanName(name);
//根据beanName找其单例
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
if (this.logger.isDebugEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//返回对应的实例
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
//原型模式下,如果这个bean已经正在创建中,说明是如下情况
//A中有B的属性,B中有A的属性,当依赖注入的时候,就回产生当A还未创建完的时候,
//因为对于B的创建,再次返回创建A,造成循环依赖
//所以就会报错
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//获取父工厂
BeanFactory parentBeanFactory = this.getParentBeanFactory();
//如果本工厂没有这个bean,存在父工厂,就去父工厂找
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
String nameToLookup = this.originalBeanName(name);
//注意下面是递归地去父工厂找
if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
}
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
//如果不是仅仅做类检查则是创建bean,这里要进行记录
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
String[] var11;
//如果存在依赖,就递归地先去实例化依赖的bean
if (dependsOn != null) {
var11 = dependsOn;
int var12 = dependsOn.length;

for(int var13 = 0; var13 < var12; ++var13) {
String dep = var11[var13];
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
this.registerDependentBean(dep, beanName);
this.getBean(dep);
}
}
if (mbd.isSingleton()) {
//单例模式的创建
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
//原型模式的创建
var11 = null;
Object prototypeInstance;
try {
//创建原型之前,先把prototypesCurrentlyInCreation里塞值,表示当前正在创建哪些原型
this.beforePrototypeCreation(beanName);
//注意到createBean这个方法留给了子类去实现
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
//移出prototypesCurrentlyInCreation,表示创建这个原型结束
this.afterPrototypeCreation(beanName);
}

bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
//其它模式的创建(指定的scope上实例化bean
String scopeName = mbd.getScope();
Scope 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, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
AbstractBeanFactory.this.beforePrototypeCreation(beanName);

Object var1;
try {
var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
} finally {
AbstractBeanFactory.this.afterPrototypeCreation(beanName);
}
return var1;
}
});
bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var21) {
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", var21);
}
}
} catch (BeansException var23) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var23;
}
}

if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
//检查类型是否符合bean的实际类型
try {
return this.getTypeConverter().convertIfNecessary(bean, requiredType);
} catch (TypeMismatchException var22) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var22);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
} else {
return bean;
}
}

提炼大致步骤

这120多行的代码,Spring都并没有再进行重构,可见其复杂程度,辛亏有书本解释,了解到大致步骤:

  1. 转换对应的beanName,因为传入的参数可能是alias

    从其具体方法中看,是之前见过的, 处理& 和别名的递归寻找本名.

    去前面笔记中寻找,在 SimpleAliasRegistry 中已经研究过此方法

  2. 尝试从缓存中加载单例

    此时可能从缓存中取出的是还没创建好的bean,主要是因为防止循环依赖

  3. bean的实例化

    如果从缓存中得到了bean的原始状态,则需要对bean进行实例化.

  4. 原型模式的依赖检查

  5. 检测parentBeanFactory

  6. 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition

  7. 寻找依赖

    因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean.

  8. 针对不同的scope进行bean的创建

  9. 类型转换

    有可能有这种情况,返回的bean,是个String,但是requiredType传入的是Integer类型,那么这时候本步骤就会起作用了. Spring中提供了各种各样的转换器,用户也可以自己扩展转换器来满足需求