1. 背景
Spring框架本身非常庞大,源码阅读可以从Spring IOC容器的实现开始一点点了解。然而即便是IOC容器,代码仍然是非常多,短时间内全部精读完并不现实 本文分析比较浅,而完整的IOC创建bean实际上是非常复杂的。本文对于BeanDefinition的加载解析,bean实例化的反射调用细节不作介绍,仅以较为粗略的角度来大体感受IOC容器创建bean的过程。
本文涉及的Spring源码版本为4.3.5.RELEASE。
2. 想要了解什么
下面就抛出几个想要了解的问题,也是本文介绍所要围绕的关键点。
- BeanFactory和ApplicationContext的区别
- IOC容器创建Bean的大致过程
- Bean的循环依赖是如何解决的
- 那些Aware究竟是什么
3. 从源码中找出问题的答案
3.1 BeanFactory & ApplicationContext
3.1.1 BeanFactory体系
org.springframework.beans.factory.BeanFactory是Spring的Bean容器的一个非常基本的接口,位于spring-beans模块。它包括了各种getBean方法,如通过名称、类型、参数等,试图从Bean容器中返回一个Bean实例。还包括诸如containsBean, isSingleton, isPrototype等方法判断Bean容器中是否存在某个Bean或是判断Bean是否为单例/原型等等。
- ListableBeanFactory 在BeanFactory基础上,支持对Bean容器中Bean的枚举。
- HierarchicalBeanFactory -> ConfigurableBeanFactory HierarchicalBeanFactory有个getParentBeanFactory方法,使得Bean容器具有亲缘关系。而ConfigurableBeanFactory则是对BeanFactory的一系列配置功能提供了支持。
- AutowireCapableBeanFactory 提供了一系列用于自动装配Bean的方法,用户代码比较少用到,更多是作为Spring内部使用。
3.1.2 ApplicationContext体系
org.springframework.context.ApplicationContext是Spring上下文的底层接口,位于spring-context模块。它可以视作是Spring IOC容器的一种高级形式,也是我们用Spring企业开发时必然会用到的接口,它含有许多面向框架的特性,也对应用环境作了适配。
从上面的图中,我们可以看到ApplicationContext作为BeanFactory的子接口,与BeanFactory之间也是通过HierarchicalBeanFactory与ListableBeanFactory桥接的。 ApplicationContext接口,继承了MessageSource, ResourceLoader, ApplicationEventPublisher接口,以BeanFactory为主线添加了许多高级容器特性。
3.2 Spring创建Bean的大致过程
搞清楚整个Spring IOC容器创建Bean的过程,对于阅读源码的效率会有很大的提升。 下面梳理一下整个过程:
- 实例化BeanFactoryPostProcessor实现类
- 调用BeanFactoryPostProcessor#postProcessBeanFactory
- 实例化BeanPostProcessor实现类
- 调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
- 实例化Bean
- 调用InstantiationAwareBeanProcessor#postProcessAfterInstantiation
- 调用InstantiationAwareBeanPostProcessor#postProcessPropertyValues
- 为Bean注入属性
- 调用BeanNameAware#setBeanName
- 调用BeanClassLoaderAware#setBeanClassLoader
- 调用BeanFactoryAware#setBeanFactory
- 调用BeanPostProcessor#postProcessBeforeInitialization
- 调用InitializingBean#afterPropertiesSet
- 调用Bean的init-method
- 调用BeanPostProcessor#postProcessAfterInitialization
3.3 IOC容器依赖注入
完整来说,IOC容器的初始化过程中做了在容器中建立BeanDefinition的数据映射。之后所有的依赖的注入都依托于已经存在的BeanDefinition,限于篇幅,此处略去对BeanDefinition的建立作介绍。直接从上下文的getBean开始看起。
在AbstractApplicationContext抽象类中有一个getBeanFactory方法用于返回一个ConfigurableListableBeanFactory,所有BeanFactory接口的方法实际上都委托给子类内部的ConfigurableListableBeanFactory实现。
我们以AnnotationConfigApplicationContext,它在被构造时,内部的beanFactory实际上是由父类GenericApplicationContext来初始化一个DefaultListableBeanFactory的。
因此我们看某个bean是如何被加载的可以从DefaultListableBeanFactory的getBean方法看起,对于DefaultListableBeanFactory而言那些getBean方法实际上在AbstractBeanFactory这一层就都已经实现了,并且都委托给了AbstractBeanFactory#doGetBean。下面就来看一下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
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
/*
* 尝试从缓存中拿取一个bean实例。
* Spring会在Bean还没完全初始化完毕的前,通过一个ObjectFactory提前暴露出bean实例,这样为解决循环依赖提供了遍历。
*/
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 + "'");
}
}
// 对FactoryBean的情况进行特殊处理。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果正在创建的bean为原型并且已经正在创建,这种循环依赖是无法解决的,要抛出异常。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果该beanFactory中不包含要创建bean的beanDefinition,则尝试从父beanFactory中寻找。
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 有些bean是有depends-on/@DependsOn的,需要先初始化这些依赖。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
getBean(dep);
}
}
// 创建单例bean。
if (mbd.isSingleton()) {
/*
* 调用父类DefaultSingletonBeanRegistry的getSingleton,具体创建bean的工作实际上仍然是
* 回调参数中传递的ObjectFactory#getObject方法,而createBean实际上是子类AbstractAutowireCapableBeanFactory实现的。
*/
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
// 对FactoryBean的情况进行特殊处理。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 创建原型bean。
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
// 前置处理,维护prototypesCurrentlyInCreation,加入当前bean记录。
beforePrototypeCreation(beanName);
// 委托给子类AbstractAutowireCapableBeanFactory来完成具体的创建bean工作。
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 后置处理,维护prototypesCurrentlyInCreation信息,删除当前bean记录。
afterPrototypeCreation(beanName);
}
// 对FactoryBean的情况进行特殊处理。
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final 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>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
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就已经创建完了,最后一步检查类型,如果不匹配会尝试转换。
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;
}
上面针对AbstractBeanFactory#doGetBean方法进行了源码分析,从中我们可以看出它主要会干这几件事情:
- 转换beanName。
- 尝试从缓存的单例中拿实例。
- 如果要创建的bean是原型模式,且已经在尝试创建,这种循环依赖是无法解决的。
- 当前beanFactory不包含要创建的bean的beanDefinition,会尝试从parentBeanFactory中获取。
- 如果当前bean有依赖(xml的话就是有depends-on,注解的话有@DependsOn),则需要先完成那些bean的创建初始化。
- 针对scope分类讨论创建。我们比较关心的就是单例,其次是原型。
- 类型检查,并且尝试转换。
我们一般比较关心的就是单例bean和原型bean的创建。 在获取单例bean时doGetBean方法会调用父类DefaultSingletonBeanRegistry#getSingleton。可以把DefaultSingletonBeanRegistry当作一个“单例bean桶”,因为它确实就是一个用来存放单例bean的桶。但是这个桶本身不关心bean到底该怎么创建,所以对于桶里还没有的bean,它将创建bean的职责通过回调ObjectFactory#getObject来完成,而AbstractBeanFactory中传递给getSingleton方法的ObjectFactory#getObject的具体实现是调用createBean,这个方法是真正创建并初始化bean的方法,由子类AbstractAutowireCapableBeanFactory完成。 对于获取原型bean则简单多了,不用关心放到桶里缓存的事情,直接调用createBean创建就是了。
所以我们接下来通过AbstractAutowireCapableBeanFactory来看一下一个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
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
/*
* 在对象被实例化前,这里有一个短路逻辑,会调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation。
* 如果存在某个InstantiationAwareBeanPostProcessor的调用结果不为null,则形成了短路,接下来调用BeanPostProcessor#postProcessAfterInitialization。
*
* 实际上,一般Spring里默认就LazyInitTargetSourceCreator和QuickTargetSourceCreator可能会使得这里的短路生效。
* 大部分情况AOP还是在bean被正常实例化后通过调用postProcessAfterInitialization实现的。
*/
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 创建bean的主要方法。
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
从上面可以看到AbstractAutowireCapableBeanFactory#createBean是创建bean的主要入口方法,但仍然不是最主要在“干活”的方法。继续向下看doCreateBean方法。
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
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 尝试从factoryBean缓存中获取。
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建bean实例。
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
/*
* Spring为了解决单例bean的循环引用问题,会在bean还没有完全初始化完毕前通过添加singletonFactory
* 使得其它bean可以拿到某个bean的实例引用。
*/
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// 接下去初始化bean。
Object exposedObject = bean;
try {
// 填充bean中的属性。
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
/*
* 调用初始化方法,比如:
* 1. 各种aware回调
* 2. 调用BeanPostProcessor#postProcessBeforeInitialization
* 3. 调用InitializingBean#afterPropertiesSet, xml中的init-method
* 4. 调用BeanPostProcessor#postProcessAfterInitialization
*/
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
/*
* 上面的getSingleton第二个参数为false表示不会主动触发early reference的创建。
* 所以此处earlySingletonReference只有在bean创建过程中发现有别的bean与当前bean有循环依赖才不为空。
*/
if (earlySingletonReference != null) {
/*
* 如果当前bean调用initializeBean没有增强原始bean实例,则取earlySingletonReference。
*
* 举例:
* BeanA与BeanB互相依赖。Srping先创建BeanA,再创建BeanB。
* BeanA通过addSingletonFactory暴露了获取BeanA引用的途径。
*
* 在populateBean的时候需要注入BeanB,而BeanB又需要注入BeanA,
* 则在获取BeanA时会调用原先BeanA暴露的ObjectFactory,继而使得earlySingletonObjects中加入了BeanA引用。
*
* 回到BeanA的创建过程,走到此步时,发现initializeBean没有增强原始bean实例,
* 则需要取其它循环依赖bean拿BeanA时在registry留下的结果(原始bean经过SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference回调)。
*/
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// 获取当前bean依赖的其它bean。
String[] dependentBeans = getDependentBeans(beanName);
// 过滤筛选出真正依赖的bean。
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
/*
* 举例:
* BeanA与BeanB互相依赖。Srping先创建BeanA,再创建BeanB。
* BeanA的创建走到这里时会抛出异常。
*
* 原因是上面的exposedObject != bean说明initializeBean方法的调用增强了原始的BeanA。
* 而BeanB中注入的BeanA很可能是原始beanA(可能会有SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference回调,
* 也就是BeanB中注入的BeanA不是此处BeanA的最终版exposedObject。
*/
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
3.4 Bean的循环依赖是如何解决的
不是所有的循环依赖Spring都能够解决的。
对于最简单的情况,bean为单例,且使用Autowired或者setter注入,Spring是可以解决这样的循环依赖的。通过上面的代码中我们可以看出,在一个Bean实例化后,会调用addSingletonFactory方法,在IOC容器中通过一个ObjectFactory暴露出可以获取还未完全初始化完毕的bean引用。若存在循环依赖,则依赖的bean可以在调用getBean时通过getSingleton方法获取到循环依赖的bean。
但是Spring是不允许出现原型环的,举例来说,BeanA和BeanB循环依赖且scope都为prototype。因为prototype的bean,不会触发addSingletonFactory,即每次get这样的bean都会新创建一个。所以创建BeanA需要注入一个BeanB,而这个BeanB又需要注入一个新的BeanA,这样的循环依赖是没办法解决的。Spring会判断当前bean是否是prototype并且已经在创建中,然后抛出异常。
对于构造器依赖,可以作一下讨论,下面讨论的bean的scope都为单例
- 如果BeanA构造器中依赖BeanB,并且BeanA先创建,则无论BeanB以哪种形式依赖BeanA,都没办法解决这样的循环依赖。因为实例化BeanA需要先得到BeanB(此时还未提前暴露引用),BeanB依赖BeanA,但是拿不到BeanA提前暴露的引用,这就形成了无限循环。这种情况会在BeanB试图获取BeanA时在beforeSingletonCreation方法抛出异常。
- 如果BeanA非构造器依赖BeanB,并且BeanA先创建,BeanB即使构造器依赖BeanA,也可以进行解决循环依赖。 因为这种情况BeanB可以拿到BeanA提前暴露的引用。
3.5 那些Aware究竟是什么
Spring中有很多XXXAware接口,从字面意思上很容易理解:就是bean能够“感知”XXX。通常这些接口的方法都是setXXX。在项目里做一个工具类实现ApplicationContextAware接口,里面可以塞一个ApplicationContext实例到静态域中,在代码中就可以很方便获取到Spring上下文进行一些操作。
那么Spring对于这些Aware接口是在哪一步调用的呢?答案其实在上面的源码分析中已经提到。在AbstractAutowireCapableBeanFactory#initializeBean方法中,Spring默认会对实现BeanNameAware, BeanClassLoaderAware, BeanFactoryAware进行回调,为它们注入beanName, classLoader, beanFactory等。
而对于更多的一些扩展,Spring基于那些processor实现了很强的可拓展性与可插拔性。比如我们非常熟悉的ApplicationContextAware接口实际上是通过ApplicationContextAwareProcessor来实际调用的,它继承了BeanPostProcessor,其中postProcessBeforeInitialization方法中会对EnvironmentAware, EmbeddedValueResolverAware, ApplicationContextAware等等一系列Aware接口的子类Bean进行回调,为其注入相关资源。
那么ApplicationContextAwareProcessor是什么时候出现在BeanPostProcessor集合中的呢?在AbstractApplicationContext#prepareBeanFactory方法中,Spring有如下代码:
1
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
也就是当Spring上下文在初始化prepareBeanFactory的时候就已经添加了ApplicationContextAwareProcessor。

