代码入口
上文【Spring源码分析】Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了finishBeanFactoryInitialization方法完成了对于所有非懒加载的Bean的初始化。
finishBeanFactoryInitialization方法中调用了DefaultListableBeanFactory的preInstantiateSingletons方法,本文针对preInstantiateSingletons进行分析,解读一下Spring是如何初始化Bean实例对象出来的。
DefaultListableBeanFactory的preInstantiateSingletons方法
DefaultListableBeanFactory的preInstantiateSingletons方法,顾名思义,初始化所有的单例Bean,看一下方法的定义:

1 public void preInstantiateSingletons() throws BeansException {
2 if (this.logger.isInfoEnabled()) {
3 this.logger.info("Pre-instantiating singletons in " + this);
4 }
5 synchronized (this.beanDefinitionMap) {
6 // Iterate over a copy to allow for init methods which in turn register new bean definitions.
7 // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
8 List beanNames = new ArrayList(this.beanDefinitionNames);
9 for (String beanName : beanNames) {
10 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
11 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
12 if (isFactoryBean(beanName)) {
13 final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
14 boolean isEagerInit;
15 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
16 isEagerInit = AccessController.doPrivileged(new PrivilegedAction() {
17 public Boolean run() {
18 return ((SmartFactoryBean) factory).isEagerInit();
19 }
20 }, getAccessControlContext());
21 }
22 else {
23 isEagerInit = (factory instanceof SmartFactoryBean &&
24 ((SmartFactoryBean) factory).isEagerInit());
25 }
26 if (isEagerInit) {
27 getBean(beanName);
28 }
29 }
30 else {
31 getBean(beanName);
32 }
33 }
34 }
35 }
36 }

这里先解释一下getMergedLocalBeanDefinition方法的含义,因为这个方法会常常看到。Bean定义公共的抽象类是AbstractBeanDefinition,普通的Bean在Spring加载Bean定义的时候,实例化出来的是GenericBeanDefinition,而Spring上下文包括实例化所有Bean用的AbstractBeanDefinition是RootBeanDefinition,这时候就使用getMergedLocalBeanDefinition方法做了一次转化,将非RootBeanDefinition转换为RootBeanDefinition以供后续操作。
解释完了getMergedLocalBeanDefinition方法的作用,第1行~第10行的代码就没什么好说的了,根据beanName拿到RootBeanDefinition而已。由于此方法实例化的是所有非懒加载的单例Bean,因此要实例化Bean,必须满足11行的三个定义:
(1)不是抽象的
(2)必须是单例的
(3)必须是非懒加载的
接着简单看一下第12行~第29行的代码,这段代码主要做的是一件事情:首先判断一下Bean是否FactoryBean的实现,接着判断Bean是否SmartFactoryBean的实现,假如Bean是SmartFactoryBean的实现并且eagerInit(这个单词字面意思是渴望加载,找不到一个好的词语去翻译,意思就是定义了这个Bean需要立即加载的意思)的话,会立即实例化这个Bean。Java开发人员不需要关注这段代码,因为SmartFactoryBean基本不会用到,我翻译一下Spring官网对于SmartFactoryBean的定义描述:
- FactoryBean接口的扩展接口。接口实现并不表示是否总是返回单独的实例对象,比如FactoryBean.isSingleton()实现返回false的情况并不清晰地表示每次返回的都是单独的实例对象
- 不实现这个扩展接口的简单FactoryBean的实现,FactoryBean.isSingleton()实现返回false总是简单地告诉我们每次返回的都是单独的实例对象,暴露出来的对象只能够通过命令访问
- 注意:这个接口是一个有特殊用途的接口,主要用于框架内部使用与Spring相关。通常,应用提供的FactoryBean接口实现应当只需要实现简单的FactoryBean接口即可,新方法应当加入到扩展接口中去
代码示例
为了后面的代码分析方便,事先我定义一个Bean:

1 package org.xrq.action;
2
3 import org.springframework.beans.factory.BeanClassLoaderAware;
4 import org.springframework.beans.factory.BeanNameAware;
5 import org.springframework.beans.factory.InitializingBean;
6
7 public class MultiFunctionBean implements InitializingBean, BeanNameAware, BeanClassLoaderAware {
8
9 private int propertyA;
10
11 private int propertyB;
12
13 public int getPropertyA() {
14 return propertyA;
15 }
16
17 public void setPropertyA(int propertyA) {
18 this.propertyA = propertyA;
19 }
20
21 public int getPropertyB() {
22 return propertyB;
23 }
24
25 public void setPropertyB(int propertyB) {
26 this.propertyB = propertyB;
27 }
28
29 public void initMethod() {
30 System.out.println("Enter MultiFunctionBean.initMethod()");
31 }
32
33 @Override
34 public void setBeanClassLoader(ClassLoader classLoader) {
35 System.out.println("Enter MultiFunctionBean.setBeanClassLoader(ClassLoader classLoader)");
36 }
37
38 @Override
39 public void setBeanName(String name) {
40 System.out.println("Enter MultiFunctionBean.setBeanName(String name)");
41 }
42
43 @Override
44 public void afterPropertiesSet() throws Exception {
45 System.out.println("Enter MultiFunctionBean.afterPropertiesSet()");
46 }
47
48 @Override
49 public String toString() {
50 return "MultiFunctionBean [propertyA=" + propertyA + ", propertyB=" + propertyB + "]";
51 }
52
53 }

定义对应的spring.xml:

1
2
6
7
8
9

利用这个MultiFunctionBean,我们可以用来探究Spring加载Bean的多种机制。
doGetBean方法构造Bean流程
上面把getBean之外的代码都分析了一下,看代码就可以知道,获取Bean对象实例,都是通过getBean方法,getBean方法最终调用的是DefaultListableBeanFactory的父类AbstractBeanFactory类的doGetBean方法,因此这部分重点分析一下doGetBean方法是如何构造出一个单例的Bean的。
看一下doGetBean方法的代码实现,比较长:

1 protected T doGetBean(
2 final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
3 throws BeansException {
4
5 final String beanName = transformedBeanName(name);
6 Object bean;
7
8 // Eagerly check singleton cache for manually registered singletons.
9 Object sharedInstance = getSingleton(beanName);
10 if (sharedInstance != null && args == null) {
11 if (logger.isDebugEnabled()) {
12 if (isSingletonCurrentlyInCreation(beanName)) {
13 logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
14 "' that is not fully initialized yet - a consequence of a circular reference");
15 }
16 else {
17 logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
18 }
19 }
20 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
21 }
22
23 else {
24 // Fail if we're already creating this bean instance:
25 // We're assumably within a circular reference.
26 if (isPrototypeCurrentlyInCreation(beanName)) {
27 throw new BeanCurrentlyInCreationException(beanName);
28 }
29
30 // Check if bean definition exists in this factory.
31 BeanFactory parentBeanFactory = getParentBeanFactory();
32 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
33 // Not found -> check parent.
34 String nameToLookup = originalBeanName(name);
35 if (args != null) {
36 // Delegation to parent with explicit args.
37 return (T) parentBeanFactory.getBean(nameToLookup, args);
38 }
39 else {
40 // No args -> delegate to standard getBean method.
41 return parentBeanFactory.getBean(nameToLookup, requiredType);
42 }
43 }
44
45 if (!typeCheckOnly) {
46 markBeanAsCreated(beanName);
47 }
48
49 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
50 checkMergedBeanDefinition(mbd, beanName, args);
51
52 // Guarantee initialization of beans that the current bean depends on.
53 String[] dependsOn = mbd.getDependsOn();
54 if (dependsOn != null) {
55 for (String dependsOnBean : dependsOn) {
56 getBean(dependsOnBean);
57 registerDependentBean(dependsOnBean, beanName);
58 }
59 }
60
61 // Create bean instance.
62 if (mbd.isSingleton()) {
63 sharedInstance = getSingleton(beanName, new ObjectFactory() {
64 public Object getObject() throws BeansException {
65 try {
66 return createBean(beanName, mbd, args);
67 }
68 catch (BeansException ex) {
69 // Explicitly remove instance from singleton cache: It might have been put there
70 // eagerly by the creation process, to allow for circular reference resolution.
71 // Also remove any beans that received a temporary reference to the bean.
72 destroySingleton(beanName);
73 throw ex;
74 }
75 }
76 });
77 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
78 }
79
80 else if (mbd.isPrototype()) {
81 // It's a prototype -> create a new instance.
82 Object prototypeInstance = null;
83 try {
84 beforePrototypeCreation(beanName);
85 prototypeInstance = createBean(beanName, mbd, args);
86 }
87 finally {
88 afterPrototypeCreation(beanName);
89 }
90 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
91 }
92
93 else {
94 String scopeName = mbd.getScope();
95 final Scope scope = this.scopes.get(scopeName);
96 if (scope == null) {
97 throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
98 }
99 try {
100 Object scopedInstance = scope.get(beanName, new ObjectFactory() {
101 public Object getObject() throws BeansException {
102 beforePrototypeCreation(beanName);
103 try {
104 return createBean(beanName, mbd, args);
105 }
106 finally {
107 afterPrototypeCreation(beanName);
108 }
109 }
110 });
111 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
112 }
113 catch (IllegalStateException ex) {
114 throw new BeanCreationException(beanName,
115 "Scope '" + scopeName + "' is not active for the current thread; " +
116 "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
117 ex);
118 }
119 }
120 }
121
122 // Check if required type matches the type of the actual bean instance.
123 if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
124 try {
125 return getTypeConverter().convertIfNecessary(bean, requiredType);
126 }
127 catch (TypeMismatchException ex) {
128 if (logger.isDebugEnabled()) {
129 logger.debug("Failed to convert bean '" + name + "' to required type [" +
130 ClassUtils.getQualifiedName(requiredType) + "]", ex);
131 }
132 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
133 }
134 }
135 return (T) bean;
136 }

首先第9行~第21行的代码,第9行的代码就不进去看了,简单说一下:首先检查一下本地的单例缓存是否已经加载过Bean,没有的话再检查earlySingleton缓存是否已经加载过Bean(又是early,不好找到词语翻译),没有的话执行后面的逻辑。
接着第26行~第50行,这里执行的都是一些基本的检查和简单的操作,包括bean是否是prototype的(prototype的Bean当前创建会抛出异常)、是否抽象的、将beanName加入alreadyCreated这个Set中等。
接着第53行~第59行,我们经常在bean标签中看到depends-on这个属性,就是通过这段保证了depends-on依赖的Bean会优先于当前Bean被加载。
接着第62行~第78行、第80行~第91行、第93行~第120行有三个判断,显然上面的MultiFunctionBean是一个单例的Bean也是本文探究的重点,因此执行第62行~第78行的逻辑。getSingleton方法不贴了,有一些前置的判断,很简单的逻辑,重点就是调用了ObjectFactory的getObject()方法来获取到单例Bean对象,方法的实现是调用了createBean方法,createBean方法是AbstractBeanFactory的子类AbstractAutowireCapableBeanFactory的一个方法,看一下它的方法实现:

1 protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
2 throws BeanCreationException {
3
4 if (logger.isDebugEnabled()) {
5 logger.debug("Creating instance of bean '" + beanName + "'");
6 }
7 // Make sure bean class is actually resolved at this point.
8 resolveBeanClass(mbd, beanName);
9
10 // Prepare method overrides.
11 try {
12 mbd.prepareMethodOverrides();
13 }
14 catch (BeanDefinitionValidationException ex) {
15 throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
16 beanName, "Validation of method overrides failed", ex);
17 }
18
19 try {
20 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
21 Object bean = resolveBeforeInstantiation(beanName, mbd);
22 if (bean != null) {
23 return bean;
24 }
25 }
26 catch (Throwable ex) {
27 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
28 "BeanPostProcessor before instantiation of bean failed", ex);
29 }
30
31 Object beanInstance = doCreateBean(beanName, mbd, args);
32 if (logger.isDebugEnabled()) {
33 logger.debug("Finished creating instance of bean '" + beanName + "'");
34 }
35 return beanInstance;
36 }

前面的代码都没什么意义,代码执行到第31行:

1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
2 // Instantiate the bean.
3 BeanWrapper instanceWrapper = null;
4 if (mbd.isSingleton()) {
5 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
6 }
7 if (instanceWrapper == null) {
8 instanceWrapper = createBeanInstance(beanName, mbd, args);
9 }
10 final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
11 Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
12
13 // Allow post-processors to modify the merged bean definition.
14 synchronized (mbd.postProcessingLock) {
15 if (!mbd.postProcessed) {
16 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
17 mbd.postProcessed = true;
18 }
19 }
20
21 // Eagerly cache singletons to be able to resolve circular references
22 // even when triggered by lifecycle interfaces like BeanFactoryAware.
23 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
24 isSingletonCurrentlyInCreation(beanName));
25 if (earlySingletonExposure) {
26 if (logger.isDebugEnabled()) {
27 logger.debug("Eagerly caching bean '" + beanName +
28 "' to allow for resolving potential circular references");
29 }
30 addSingletonFactory(beanName, new ObjectFactory() {
31 public Object getObject() throws BeansException {
32 return getEarlyBeanReference(beanName, mbd, bean);
33 }
34 });
35 }
36
37 // Initialize the bean instance.
38 Object exposedObject = bean;
39 try {
40 populateBean(beanName, mbd, instanceWrapper);
41 if (exposedObject != null) {
42 exposedObject = initializeBean(beanName, exposedObject, mbd);
43 }
44 }
45 catch (Throwable ex) {
46 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
47 throw (BeanCreationException) ex;
48 }
49 else {
50 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
51 }
52 }
53
54 if (earlySingletonExposure) {
55 Object earlySingletonReference = getSingleton(beanName, false);
56 if (earlySingletonReference != null) {
57 if (exposedObject == bean) {
58 exposedObject = earlySingletonReference;
59 }
60 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
61 String[] dependentBeans = getDependentBeans(beanName);
62 Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
63 for (String dependentBean : dependentBeans) {
64 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
65 actualDependentBeans.add(dependentBean);
66 }
67 }
68 if (!actualDependentBeans.isEmpty()) {
69 throw new BeanCurrentlyInCreationException(beanName,
70 "Bean with name '" + beanName + "' has been injected into other beans [" +
71 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
72 "] in its raw version as part of a circular reference, but has eventually been " +
73 "wrapped. This means that said other beans do not use the final version of the " +
74 "bean. This is often the result of over-eager type matching - consider using " +
75 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
76 }
77 }
78 }
79 }
80
81 // Register bean as disposable.
82 try {
83 registerDisposableBeanIfNecessary(beanName, bean, mbd);
84 }
85 catch (BeanDefinitionValidationException ex) {
86 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
87 }
88
89 return exposedObject;
90 }

代码跟踪到这里,已经到了主流程,接下来分段分析doCreateBean方法的代码。
创建Bean实例
第8行的createBeanInstance方法,会创建出Bean的实例,并包装为BeanWrapper,看一下createBeanInstance方法,只贴最后一段比较关键的:

1 // Need to determine the constructor...
2 Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
3 if (ctors != null ||
4 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
5 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
6 return autowireConstructor(beanName, mbd, ctors, args);
7 }
8
9 // No special handling: simply use no-arg constructor.
10 return instantiateBean(beanName, mbd);

意思是bean标签使用构造函数注入属性的话,执行第6行,否则执行第10行。MultiFunctionBean使用默认构造函数,使用setter注入属性,因此执行第10行代码:

1 protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
2 try {
3 Object beanInstance;
4 final BeanFactory parent = this;
5 if (System.getSecurityManager() != null) {
6 beanInstance = AccessController.doPrivileged(new PrivilegedAction