spring獲取bean的源碼解析
介紹
前面一章說瞭AbstractApplicationContext中的refresh方法中的invokeBeanFactoryPostProcessors。主要是調用BeanFactoryPostProcessor。其中也有獲取bean的過程,就是beanFactory.getBean的方法。這一章就說下getBean這個方法。由於spring中獲取bean的方法比較復雜,涉及到的流程也非常多,這一章就先說下整個大體的流程。其中的細節會在後面也會慢慢說。
源碼
直接看源碼吧
@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } @Override public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException { return doGetBean(name, requiredType, null, false); } @Override public Object getBean(String name, Object... args) throws BeansException { return doGetBean(name, null, args, false); } public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException { return doGetBean(name, requiredType, args, false); } @SuppressWarnings("unchecked") protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // 把name轉化成beanName,也就是把FactoryBean的名稱轉化成beanName如果有別名則用別名 final String beanName = transformedBeanName(name); Object bean; // 從緩存中獲取實例 // 可能是需要的Bean實例,也可能是FactoryBean 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 + "'"); } } // 獲取需要的bean或者FactoryBean bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 判斷prototype類型的bean是否存在循環引用 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 校驗父類BeanFactory BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // 父類去獲取bean String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } } // 標記成已創建 if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // 把原來BeanDefinition轉換成RootBeanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 獲取依賴的bean,也就是通過@DependsOn註入進來的bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 校驗dependsOn的bean是否存在循環應用 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 加入到引用的緩存中,由於校驗dependsOn循環引用 registerDependentBean(dep, beanName); // 獲取@dependsOn的bean getBean(dep); } } // 創建單例的bean if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); // 獲取需要的bean或者FactoryBean bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 創建prototype的bean else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } // 創建其他的bean,比如session,request等 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, () -> { 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 && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } 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; }
獲取bean的整體流程就像上面源碼所示,這裡再梳理下spring獲取bean的整個流程
1.先轉換bean的名稱,轉換成beanName。這裡意思就是,我們在獲取bean的時候,可能是FactoryBean的名稱(&開頭),這裡轉成不帶&開頭的名稱,如果有別名,再獲取別名。
2.從緩存中獲取bean,這裡的緩存分為一二三級緩存,也就是我們常常被問到瞭spring三級緩存,具體邏輯下面再說。
3.根據獲取的到對象再去獲取我們想要的bean,因為這裡獲取到的對象可能是我們需要的bean,也可能是FactoryBean。
4.如果緩存中沒有,那麼我們就要自己去創建bean瞭。
5.查看有沒有父類的BeanFactory,如果有,那麼就父類去創建bean。
6.獲取要創建的bean對象的@DependsOn註解上的名稱,先去創建DependsOn的bean,並且校驗是否存在循環引用
7.創建bean,根據類型創建不同的bean,比如singleton,prototype,request,session等。
8.如果需要轉換類型,則進行類型轉換。
整體的獲取bean的流程就是這樣瞭,其中有些具體流程接著分析。
從緩存中獲取bean對象
public Object getSingleton(String beanName) { return getSingleton(beanName, true); } @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 從一級緩存中獲取 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 從二級緩存中獲取 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 從三級緩存中獲取 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
spring通過三級緩存來解決循環依賴的問題。簡單來介紹下三級緩存。
1. singletonObjects為一級緩存,我們實例化的bean都在這個map裡,俠義的說singletonObjects才是我們真正的spring容器,存放bean的地方。
2. earlySingletonObjects為二級緩存,是存放未完成的bean的緩存,如果有代理的話,存放的是代理對象。
3. singletonFactories為三級緩存,存放的是一個ObjectFactory,數據通過getObject方法獲得。
從BeanInstance中獲取對象
接下來看getObjectForBeanInstance方法。
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // name是不是factoryBean的name(&開頭的) if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } // 如果是FactoryBeanName,但是獲取到的bean不是FactoryBean,則拋異常 if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); } } // 如果bean不是FactoryBean,或者名稱是FactoryBeanName,直接返回BeanInstace if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null; if (mbd == null) { // 從緩存中獲取 object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // 這裡可以確定beanInstance是FactoryBean瞭 FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); // 通過FactoryFBean中獲取需要的beanInstance object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
這裡是通過BeanInstance獲取我們想要的bean,這裡也簡單說下流程
1. 首先判斷name是不是FactoryBean的name,也就是&開頭的name,如果是去判斷beanInstance是不是FactoryBean,如果beanInstance不是FactoryBean則拋異常。
2. 由於上面已經判斷過,如果name是FactoryBeanName,但是BeanInstance不是FactoryBean的話,就會拋出異常。所以如果BeanInstance如果不是FactoryBean的話,那麼name一定不是FactoryBeanName。那麼就直接返回BeanInstance就是我們需要的瞭。
如果name是FactoryBeanName,那麼我們需要獲取的就是FactoryBean,也直接返回就可以瞭。
3. 如果都沒有返回,那麼已經可以確定我們此時的已經可以確定BeanInstance是FactoryBean瞭,因為如果不是FactoryBean的話,在!(beanInstance instanceof FactoryBean)就已經返回瞭。
4. 通過FactoryBean的getObject方法獲取我們需要的bean實例。
創建bean
根據@dependsOn查找依賴的bean並且加到依賴裡面去沒有什麼好說的,代碼邏輯也很簡單,接下來看創建單例bean。其他類型的bean的創建也都差別不大。看源碼
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { // 直接從一級緩存中取 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } // 在沒創建bean之前的處理 beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { // 獲取創建的bean singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } // 創建結束之後的工作 afterSingletonCreation(beanName); } if (newSingleton) { // 加到一級緩存中,其實也就是真正的容器中瞭 addSingleton(beanName, singletonObject); } } return singletonObject; } }
對於創建單例bean的主要流程就是如此,傳入一個beanName,和一個ObjectFactory。ObjectFactory中具體實現瞭創建bean的邏輯。在看具體創建bean的邏輯之前,我們還需要去看下getSingleton中的創建bean之前的工作和創建bean之後的工作。這裡面就是查找bean的循環依賴的方法(和dependsOn不同)。主要是查找根據filed,set,構造器方法的循環依賴。
protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } } protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } }
可以看到代碼非常的簡單,就是創建bean之前,如果沒有排除依賴檢查,那麼就加入到正在創建的Set中,如果加入不進去,說明之前已經加過,這就產生瞭循環依賴,從而拋出異常。
如果在創建bean之後,沒有排除檢查依賴,並且移除失敗,說明已經不在Set中,也會拋出異常。
好瞭,既然明白瞭spring是如何校驗循環依賴的,也看到瞭三級緩存,後面再說為什麼不能解決構造器依賴就很好說瞭。接著看創建bean的方法。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // 獲取要創建bean的class Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { // 如果沒有beanclass,設置beanclass 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 { // 那些beanPostProcessor如果能產生代理,則直接返回bean 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); } try { // 創建bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException ex) { // A previously detected exception with proper bean creation context already... throw ex; } catch (ImplicitlyAppearedSingletonException ex) { // An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry... throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
這裡其實還是沒有到創建bean的過程,還是在創建bean的一些準備工作。其實我們可以發現,spring中,真正做事的都是do開頭的方法。
這邊的流程就是設置beanClass,後面需要根據反射來創建bean。然後會根據spring裡面的beanPostProcessor,看看有沒有能產生代理bean的,如果有就返回,沒有就去創建bean。
看真正的doCreateBean方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 裝飾Bean的對象 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { // 通過緩存獲取 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 創建bean instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { // 調用MergedBeanDefinitionPostProcessor的方法 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // 加入到三級緩存中去 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, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // 填充依賴的bean,field註入,和方法註入的bean populateBean(beanName, mbd, instanceWrapper); // 調用初始化的方法 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); if (earlySingletonReference != null) { // 如果一致,則直接使用二級緩存的對象 if (exposedObject == bean) { exposedObject = earlySingletonReference; } // 如果調用初始化後的bean和之前的bean不一致,並且有依賴 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { // 查找循環依賴 String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { // 如果有循環依賴並且在創建中,則拋出異常 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } 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."); } } } } // 註冊disposableBean try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
真正創建bean這裡還是有點復雜的。這裡再進行一個簡單梳理。
1. 根據class還有bean以及參數創建bean。
2. 調用beanPostprocessor的方法,調用屬於MergedBeanDefinitionPostProcessor的方法。對bean進行一些處理,比如找到那些依賴的bean的field和method。
3. 將bean加入到三級緩存中去。
4. 填充bean需要註入的其他bean。
5. 調用初始化方法,先去調用@PostConstruct註解方法,然後調用InitializingBean的afterPropertiesSet,以及自定義的init-method方法。在bean調用初始化方法之後,再去調用後置接口看看是否需要生成Aop代理。
6. 接著進行校驗。這裡稍微比較復雜一點。如果從二級緩存能取到,那就說明之前被別人從三級緩存拿出來過瞭。可能是因為循環依賴,也可能是因為別的地方調用瞭getBean方法瞭。從三級緩存拿出來的時候有個getEarlyBeanReference的方法,就是查看是否要生成代理的bean。如果生成過瞭,那麼在調用第五步的時候,就不會在生成代理瞭。這樣exposedObject ==bean,直接隻用代理返回。
如果不相等:這裡的情況就是如果是spring自己的@Async,在從二級緩存生成代理之後,再去調用第五步時候一樣會生成代理。所以exposedObject !=bean,所以在再往下發現有循環調用,並且bean還在創建時,就會拋出異常瞭。所以一般慎用spring的@Async。但是一般也可以使用@Lazy進行處理。至於原理後面再說。
到這裡spring的創建bean就結束瞭。然後返回時候就到瞭入口方法getBean的getObjectForBeanInstance的方法,到底需要的bean還是FactoryBean。
最後就是如果requiredType和實例不一樣就要進行類型轉換瞭。
總結
本篇大概說下spring獲取bean和加到容器裡面的流程。其實廣義上來說Bean的容器是BeanFactory或者applicationContext。狹義上說就是一個map。也就是一級緩存SingletonObjects。我們獲取的真正需要的bean也就是從中獲取的。本篇隻是簡要的說瞭下bean獲取和加入容器的整個流程,具體的根據無參構造器創建bean,有參數構造器創建bean。還有對於創建bean中依賴的bean的查找還有創建,三級緩存如何解決循環依賴還有為何不能解決構造器依賴,以及bean調用初始化的等等操作都沒有說。因為一篇說起來確實太長瞭。後面都會一一去分析。
到此這篇關於spring獲取bean的源碼解析的文章就介紹到這瞭,更多相關spring獲取bean源碼內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Spring中Bean註入源碼示例解析
- Spring解決循環依賴的方法(三級緩存)
- 聊聊Spring循環依賴三級緩存是否可以減少為二級緩存的情況
- Mybatis-Spring源碼分析圖解
- Spring三級緩存解決循環依賴