Spring框架自己很是龐大,源碼閱讀能夠從Spring IOC容器的實現開始一點點了解。然而即使是IOC容器,代碼仍然是很是多,短期內所有精讀完並不現實
本文分析比較淺,而完整的IOC建立bean其實是很是複雜的。本文對於BeanDefinition的加載解析,bean實例化的反射調用細節不做介紹,僅以較爲粗略的角度來大致感覺IOC容器建立bean的過程。java
本文涉及的Spring源碼版本爲4.3.5.RELEASE。spring
下面就拋出幾個想要了解的問題,也是本文介紹所要圍繞的關鍵點。緩存
org.springframework.beans.factory.BeanFactory是Spring的Bean容器的一個很是基本的接口,位於spring-beans模塊。它包括了各類getBean方法,如經過名稱、類型、參數等,試圖從Bean容器中返回一個Bean實例。還包括諸如containsBean, isSingleton, isPrototype等方法判斷Bean容器中是否存在某個Bean或是判斷Bean是否爲單例/原型等等。app
能夠看到BeanFactory向下主要有三條繼承路線框架
org.springframework.context.ApplicationContext是Spring上下文的底層接口,位於spring-context模塊。它能夠視做是Spring IOC容器的一種高級形式,也是咱們用Spring企業開發時必然會用到的接口,它含有許多面向框架的特性,也對應用環境做了適配。ide
從上面的圖中,咱們能夠看到ApplicationContext做爲BeanFactory的子接口,與BeanFactory之間也是經過HierarchicalBeanFactory與ListableBeanFactory橋接的。
ApplicationContext接口,繼承了MessageSource, ResourceLoader, ApplicationEventPublisher接口,以BeanFactory爲主線添加了許多高級容器特性。工具
搞清楚整個Spring IOC容器建立Bean的過程,對於閱讀源碼的效率會有很大的提高。
下面梳理一下整個過程:源碼分析
完整來講,IOC容器的初始化過程當中作了在容器中創建BeanDefinition的數據映射。以後全部的依賴的注入都依託於已經存在的BeanDefinition,限於篇幅,此處略去對BeanDefinition的創建做介紹。直接從上下文的getBean開始看起。post
在AbstractApplicationContext抽象類中有一個getBeanFactory方法用於返回一個ConfigurableListableBeanFactory,全部BeanFactory接口的方法實際上都委託給子類內部的ConfigurableListableBeanFactory實現。ui
咱們以AnnotationConfigApplicationContext,它在被構造時,內部的beanFactory其實是由父類GenericApplicationContext來初始化一個DefaultListableBeanFactory的。
所以咱們看某個bean是如何被加載的能夠從DefaultListableBeanFactory的getBean方法看起,對於DefaultListableBeanFactory而言那些getBean方法實際上在AbstractBeanFactory這一層就都已經實現了,而且都委託給了AbstractBeanFactory#doGetBean。下面就來看一下doGetBean方法。
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方法進行了源碼分析,從中咱們能夠看出它主要會幹這幾件事情:
咱們通常比較關心的就是單例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具體是如何建立並初始化的。
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
方法。
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; }
不是全部的循環依賴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而且已經在建立中,而後拋出異常。
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有以下代碼:
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
也就是當Spring上下文在初始化prepareBeanFactory的時候就已經添加了ApplicationContextAwareProcessor。