finishBeanFactoryInitialization方法中调用了DefaultListableBeanFactory的preInstantiateSingletons方法,本文针对preInstantiateSingletons进行分析,解读一下Spring是如何初始化Bean实例对象出来的。
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<String> beanNames = new ArrayList<String>(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<Boolean>() { 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的定义描述:
为了后面的代码分析方便,事先我定义一个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 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 6 7 <bean id="multiFunctionBean" class="org.xrq.action.MultiFunctionBean" init-method="initMethod" /> 8 9 </beans>
利用这个MultiFunctionBean,我们可以用来探究Spring加载Bean的多种机制。
上面把getBean之外的代码都分析了一下,看代码就可以知道,获取Bean对象实例,都是通过getBean方法,getBean方法最终调用的是DefaultListableBeanFactory的父类AbstractBeanFactory类的doGetBean方法,因此这部分重点分析一下doGetBean方法是如何构造出一个单例的Bean的。
看一下doGetBean方法的代码实现,比较长:
1 protected <T> T doGetBean( 2 final String name, final Class<T> 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<String> actualDependentBeans = new LinkedHashSet<String>(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方法的代码。
第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<Object>() { 7 public Object run() { 8 return getInstantiationStrategy().instantiate(mbd, beanName, parent); 9 } 10 }, getAccessControlContext()); 11 } 12 else { 13 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 14 } 15 BeanWrapper bw = new BeanWrapperImpl(beanInstance); 16 initBeanWrapper(bw); 17 return bw; 18 } 19 catch (Throwable ex) { 20 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); 21 } 22 }
代码执行到13行:
1 public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) { 2 // Don't override the class with CGLIB if no overrides. 3 if (beanDefinition.getMethodOverrides().isEmpty()) { 4 Constructor<?> constructorToUse; 5 synchronized (beanDefinition.constructorArgumentLock) { 6 constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod; 7 if (constructorToUse == null) { 8 final Class clazz = beanDefinition.getBeanClass(); 9 if (clazz.isInterface()) { 10 throw new BeanInstantiationException(clazz, "Specified class is an interface"); 11 } 12 try { 13 if (System.getSecurityManager() != null) { 14 constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() { 15 public Constructor run() throws Exception { 16 return clazz.getDeclaredConstructor((Class[]) null); 17 } 18 }); 19 } 20 else { 21 constructorToUse = clazz.getDeclaredConstructor((Class[]) null); 22 } 23 beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse; 24 } 25 catch (Exception ex) { 26 throw new BeanInstantiationException(clazz, "No default constructor found", ex); 27 } 28 } 29 } 30 return BeanUtils.instantiateClass(constructorToUse); 31 } 32 else { 33 // Must generate CGLIB subclass. 34 return instantiateWithMethodInjection(beanDefinition, beanName, owner); 35 } 36 }
整段代码都在做一件事情,就是选择一个使用的构造函数。当然第9行顺带做了一个判断:实例化一个接口将报错。
最后调用到30行,看一下代码:
1 public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { 2 Assert.notNull(ctor, "Constructor must not be null"); 3 try { 4 ReflectionUtils.makeAccessible(ctor); 5 return ctor.newInstance(args); 6 } 7 catch (InstantiationException ex) { 8 throw new BeanInstantiationException(ctor.getDeclaringClass(), 9 "Is it an abstract class?", ex); 10 } 11 catch (IllegalAccessException ex) { 12 throw new BeanInstantiationException(ctor.getDeclaringClass(), 13 "Is the constructor accessible?", ex); 14 } 15 catch (IllegalArgumentException ex) { 16 throw new BeanInstantiationException(ctor.getDeclaringClass(), 17 "Illegal arguments for constructor", ex); 18 } 19 catch (InvocationTargetException ex) { 20 throw new BeanInstantiationException(ctor.getDeclaringClass(), 21 "Constructor threw exception", ex.getTargetException()); 22 } 23 }
通过反射生成Bean的实例。看到前面有一步makeAccessible,这意味着 即使Bean的构造函数是private、protected的,依然不影响Bean的构造 。
最后注意一下,这里被实例化出来的Bean并不会直接返回,而是会被包装为BeanWrapper继续在后面使用。