由于 getBean 內容比較多, 所以單獨出來, 接著上一篇的順序來看.
//org.springframework.beans.factory.support.AbstractBeanFactory#getBean @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }
doGetBean里面, 有一堆亂七八糟的判斷,
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { /** * 通過 name 獲取 beanName,這里不使用 name 直接作為 beanName 有兩個原因 * 1、name 可能會以 & 字符開頭,表明呼叫者想獲取 FactoryBean 本身,而非 FactoryBean * 實作類所創建的 bean,在 BeanFactory 中,FactoryBean 的實作類和其他的 bean 存盤 * 方式是一致的,即 <beanName, bean>,beanName 中是沒有 & 這個字符的,所以我們需要 * 將 name 的首字符 & 移除,這樣才能從快取里取到 FactoryBean 實體, * 2、還是別名的問題,轉換需要 * &beanName */ final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. /** * 這個方法在初始化的時候會呼叫,在getBean的時候也會呼叫 * 為什么需要這么做呢? * 也就是說spring在初始化的時候先獲取這個物件 * 判斷這個物件是否被實體化好了(普通情況下絕對為空====初始化完之后, 此處回傳就不是空了) * 從spring的bean容器中獲取一個bean,由于spring中bean容器是一個map(singletonObjects) * 所以你可以理解getSingleton(beanName)等于beanMap.get(beanName) * 由于方法會在spring環境初始化的時候(就是物件被創建的時候呼叫一次)呼叫一次 * 還會在getBean的時候呼叫一次 * * 需要說明的是在初始化時候呼叫一般都是回傳null */ Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } /** * 如果 sharedInstance 是普通的單例 bean,下面的方法會直接回傳, * 但如果 sharedInstance 是 FactoryBean 型別的,則需呼叫 getObject 工廠方法獲取真正的 bean 實體, * 如果用戶想獲取 FactoryBean 本身,這里也不會做特別的處理,直接回傳即可, * 畢竟 FactoryBean 的實作類本身也是一種 bean,只不過具有一點特殊的功能而已, */ bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. /** * 原型模式 * 如果是原型不應該在初始化的時候創建 */ if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { ...... } if (!typeCheckOnly) { //添加到 alreadyCreated set集合當中,表示他已經創建過一場 markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); //bd檢測, 如果是 abstract, 則拋例外 checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. 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); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. // 單例創建 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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { ...... } else { ...... } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && !requiredType.isInstance(bean)) { ...... } return (T) bean; }
方法比較長, 我刪掉一部分. 不影響觀看.
主要看兩個方法 :
1.getSingleton(String beanName, ObjectFactory<?> singetonFactory)
2.createBean
getSingleton
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton
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 + "'"); } /** * 將beanName添加到singletonsCurrentlyInCreation這樣一個set集合中 * 表示beanName對應的bean正在創建中 */ beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { //這里會呼叫傳入的 lambda 運算式創建的匿名 singletonFactory 物件, 呼叫他的 getObject() 方法 //其方法內部, 也就是呼叫 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean 方法 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; } }
這里的getSingleton , 明顯是一個創建 bean 的地方.
1. 在創建之前, 通過 beforeSingletonCreation() 方法, 執行了 this.singletonsCurrentlyInCreation.add(beanName) 這句代碼,
這里其實是在做一個標志, 表示 這個 beanName 對應的 bean 正在創建當中. 將 singletonsCurrentlyInCreation 翻譯過來, 就能看懂.
這里做到了變數名的命名就是最好的注釋.
2. 呼叫 factory.getObject 方法, 進行 bean 的創建, 呼叫的其實就是 createBean() 方法.
3. 創建完成之后, 通過 afterSingletonCreation() 方法, 將標志位改回去, 其內部執行了 this.singletonsCurrentlyInCreation.remove(beanName) 這句代碼.
4. 在最后, 通過 addSingleton() 方法, 將創建的 bean 放到 spring 容器中 : this.singletonObjects.put(beanName, singletonObject)
這里的這個順序很重要, 尤其是那個 正在創建的標志, 很重要的 : singletonsCurrentlyInCreation
這個正在創建的標志, 在解決 回圈依賴的時候, 起了很重要的作用
createBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
@Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } //Prepare method overrides. //處理xml中的 lookup-method 和 replace-method 配置,Spring將這兩個配置統稱為override method try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. // 在 bean實體化之前 應用后置處理,如果后置處理回傳的bean不為空,則直接回傳 // 回傳的是一個寡婦物件, 屬性什么的, spring不會去維護 // spring不推薦開發人員使用這個介面 InstantiationAwareBeanPostProcessor 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.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
在 spring 里面, 有一個習慣, 喜歡把 真正干活的那個方法, 以 do 開頭.
所以, 這個 doCreateBean() 方法, 應該就是干活方法.
不過在此之前, 要看一個重要擴展方法: resolveBeforeInstantiation
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/131433.html
標籤:Java
上一篇:spring IOC - AnnotationConfigApplicationContext#refresh2
下一篇:Bean后置處理器 - InstantiationAwareBeanPostProcessor#applyBeanPostProcessorsBeforeInstantiation
