上一篇我們在Spring源碼十八:Bean實例化流程一?中,主要討論了Spring在實例化前的兩重要準備工作,1、獲取我們前面注冊好的BeanDefinition,將GenericBeanDefinition封裝為RootBeanDefinition如果Bean Definition只存在父容器中,還會進行合并操作,然后做了嚴謹的異常判斷處理。2、如果bean配置了依賴的bean的名稱,還會檢查下配置的依賴,是否已經處于bean依賴的引用鏈上了,如果沒有處于bean依賴引用鏈上,就會提前來實例化bean依賴的那些bean。最后找到實例化的入口。
?今天我們開始分析下單例bean是如何創建:咱們接著上一篇代碼往下看
getSingleton
再進入代碼中看下邏輯:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(beanName, "Bean name must not be null");synchronized (this.singletonObjects) {// 從單例緩存中獲取Bean的實例Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {// 如果當前bean正在銷毀標志為true,則拋出異常。 默認:singletonsCurrentlyInDestruction = falseif (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列表中,標志當前bean正在被創建beforeSingletonCreation(beanName);boolean newSingleton = false;boolean recordSuppressedExceptions = (this.suppressedExceptions == null);if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet<>();}try {// !!!! 調用簡單工廠方法來實例化bean !!!! //singletonObject = singletonFactory.getObject();// 標志當前bean是第一次過來,默認是falsenewSingleton = true;}catch (IllegalStateException ex) {// Has the singleton object implicitly appeared in the meantime ->// if yes, proceed with it since the exception indicates that state.// 再努力一次,如果通過簡單工廠創建失敗: 嘗試從單例緩存中,獲取beanName對應的單例beansingletonObject = 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;}// 從singletonsCurrentlyInCreation列表中移出,標志當前beanName對應的bean已經創建完成了。afterSingletonCreation(beanName);}if (newSingleton) {// 看到了嘛,看到了嘛,第一次標志在這里用的,單例緩存入的地方也再這里,哈哈 我們找到啦addSingleton(beanName, singletonObject);}}return singletonObject;}}
這段代碼是Spring框架中用于創建和獲取單例bean實例的一部分。以下是對這段代碼的分析:
-
使用lambda表達式:代碼中使用了Java 8的lambda表達式來創建一個匿名的
ObjectFactory
實例。這個ObjectFactory
會在需要時調用其getObject()
方法來創建bean。 -
getSingleton()方法:
getSingleton(beanName, singletonFactory)
方法被調用來獲取名為beanName
的單例bean。如果這個bean尚未被創建,singletonFactory.getObject()
將被調用以創建它。 -
createBean()方法:在lambda表達式中,如果bean不存在,將調用
createBean(beanName, mbd, args)
方法來創建bean。這個方法負責完整的bean創建過程,包括依賴注入、初始化等步驟。 -
異常處理:如果在創建bean的過程中拋出了
BeansException
(例如,由于循環依賴或其他bean創建問題),代碼將執行以下操作:- 調用?
destroySingleton(beanName)
?來從單例緩存中移除部分創建的bean實例。這是必要的,因為創建過程中可能會因為解決循環依賴而提前將bean放入緩存。 - 拋出原始的?
BeansException
,以通知調用者bean創建失敗。
- 調用?
-
獲取bean實例:如果bean成功創建,
sharedInstance
將包含新創建的bean實例。然后,調用getObjectForBeanInstance(sharedInstance, name, beanName, mbd)
方法來獲取bean實例對象。這個方法可能執行額外的處理,比如應用FactoryBean
的邏輯或處理bean的后置處理(post-processing)。 -
單例緩存:整個過程中,Spring使用
singletonObjects
作為緩存來存儲已經創建的單例bean。這樣,后續請求相同bean時可以直接從緩存中獲取,而不需要重新創建。
這段代碼體現了Spring框架中創建單例bean的復雜性,包括異常安全、延遲初始化和對循環依賴的處理。通過使用 ObjectFactory
和lambda表達式,Spring能夠以一種靈活且高效的方式來管理bean的生命周期。
createBean
上面我已經找到真正創建bean的地方,也看到Spring是通過簡單工廠創建實例的也驗證了人命常說的bean工廠、工廠模式。同時也看到單例bean首次創建,會放入單例緩存池中。但是整個方法有個內部類,當然這里是Java8的函數式接口實現的,咱們跳出來看下這個默認方法是做了什么邏輯處理。通過這個方法來
看到上圖標注的地方createBean見名知意,應該是這個方法包含了實例化的核心邏輯,咱們進入方法內部一探究竟之前簡單分析一下:在這個內部類里首先會通過createBean來實例化一個bena,如果實例化的過程中出現了異常,就會調用方法destroy Singleton方法,來清除單利bean相關的一系列緩存信息。
/*** Central method of this class: creates a bean instance, 創建bean實例對象* populates the bean instance, applies post-processors, etc. 填充bean實例、應用后置處理器* @see #doCreateBean*/@Overrideprotected 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. 判斷需要創建的bean是否可以實例化、是否可以通過當前類加載器加載Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides. 準備bean中的方法覆蓋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. 給BeanPostProcessors一個返回代理而不是目標bean實例的機會。Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 如果bean配置類后置處理器PostProcessor,則這里返回一個proxy代理對象if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {Object beanInstance = doCreateBean(beanName, mbdToUse, args); // bean實例對象創建方法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);}}
?