代碼入口 上文【Spring源碼分析】Bean載入流程概覽,比較詳細地分析了Spring上下文載入的代碼入口,並且在AbstractApplicationContext的refresh方法中,點出了finishBeanFactoryInitialization方法完成了對於所有非懶載入的Bean的初 ...
代碼入口
上文【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<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 }
前面的代碼比較簡單,根據beanName拿到BeanDefinition(即Bean的定義)。由於此方法實例化的是所有非懶載入的單例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 <?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的多種機制。
doGetBean方法構造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方法的代碼。
創建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<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