目錄
前置知識
????????SingletonBeanRegistry
????????DefaultSingletonBeanRegistry
Spring中處理循環引用的流程分析
????????定義兩個具有循環引用特點的Bean
????????執行A的實例化
????????執行A的屬性填充(執行過程中發現A依賴B,就去執行B的實例化邏輯)
????????執行B的實例化
????????執行B的屬性填充
????????執行B的初始化
????????執行A的屬性填充(此時依賴的B已經完成了實例化和初始化放到容器的單例池中,接著執行之前沒有執行完成的A的屬性填充邏輯)
????????執行A的初始化
前置知識
SingletonBeanRegistry
該接口中定義了一些和單例Bean有關的方法
package org.springframework.beans.factory.config;public interface SingletonBeanRegistry {/*** 往容器中添加單例bean對象*/void registerSingleton(String beanName, Object singletonObject);/*** 通過bean名字獲取bean對象*/Object getSingleton(String beanName);/*** 判斷容器中是否包含某bean名字的單例bean*/boolean containsSingleton(String beanName);/*** 獲取容器中所有單例bean的名稱集合*/String[] getSingletonNames();/*** 獲取容器中單例bean對象的數量*/int getSingletonCount();
}
DefaultSingletonBeanRegistry
- 定義了三個Map集合(也就是常說的三級緩存)
- 定義了一個Set集合,用于存儲正在創建的單例Bean的beanName
- 對SingletonBeanRegistry接口提供方法的實現
package org.springframework.beans.factory.support;public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {// 一級緩存private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);// 三級緩存private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);// 二級緩存private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);// ...// 正在創建的單例Bean的beanNameprivate final Set<String> singletonsCurrentlyInCreation =Collections.newSetFromMap(new ConcurrentHashMap<>(16));/*** 對registerSingleton方法的實現*/@Overridepublic void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {// ...synchronized (this.singletonObjects) {// 通過beanName先從一級緩存中獲取Object oldObject = this.singletonObjects.get(beanName);// 一級緩存中已經有該beanName的對象,就拋異常if (oldObject != null) {throw new IllegalStateException("Could not register object [" + singletonObject +"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");}// 一級緩存中沒有該beanName的對象,就執行添加邏輯addSingleton(beanName, singletonObject);}}/*** 往容器中添加Bean*/protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {// beanName作為key,bean對象作為value,往一級緩存中添加this.singletonObjects.put(beanName, singletonObject);// 刪除三級緩存中key為beanName的節點this.singletonFactories.remove(beanName);// 刪除二級緩存中key為beanName的節點this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}// .../*** 對getSingleton方法的實現(通過beanName獲取bean對象)*/ @Override@Nullablepublic Object getSingleton(String beanName) {// 調用重載方法return getSingleton(beanName, true);}/*** getSingleton第二個參數是boolean類型的重載方法*/@Nullableprotected Object getSingleton(String beanName, boolean allowEarlyReference) {// 先從一級緩存中獲取bean對象Object singletonObject = this.singletonObjects.get(beanName);// 一級緩存中沒有該beanName對應的對象并且該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) {// 執行三級緩存中的Lambda表達式的邏輯singletonObject = singletonFactory.getObject();// 放入二級緩存this.earlySingletonObjects.put(beanName, singletonObject);// 刪除三級緩存中key為beanName的節點this.singletonFactories.remove(beanName);}}}}// 返回bean對象return singletonObject;}/*** getSingleton的重載方法* 第二個參數為Lambda表達式,為bean的創建過程*/public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {// ...synchronized (this.singletonObjects) {// 先從一級緩存中獲取bean對象Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {// bean正在被創建,拋異常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!)");}// ...// 創建bean之前,做一個標記,標記該beanName的bean正在創建中beforeSingletonCreation(beanName);boolean newSingleton = false;// ...try {// 執行Lambda的邏輯,執行bean的實例化和初始化流程singletonObject = singletonFactory.getObject();newSingleton = true;}catch (IllegalStateException ex) {// ...}catch (BeanCreationException ex) {// ...}finally {// ...// 移除該beanName正在創建對象的標識afterSingletonCreation(beanName);}if (newSingleton) {// 將完成實例化和初始化的bean對象放入單例池中addSingleton(beanName, singletonObject);}}// 返回bean對象return singletonObject;}}
}
Spring中處理循環引用的流程分析
定義兩個具有循環引用特點的Bean
package spring.demo;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** A依賴B*/
@Component
public class A {@Autowiredprivate B b;
}
package spring.demo;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** B依賴A*/
@Component
public class B {@Autowiredprivate A a;
}
執行A的實例化
一、DefaultListableBeanFactory#preInstantiateSingletons
遍歷beanNames,根據beanName實例化非懶加載的單例Bean
二、AbstractBeanFactory#getBean
getBean - doGetBean
三、AbstractBeanFactory#doGetBean
先嘗試從容器中獲取,有就直接返回
四、DefaultSingletonBeanRegistry#getSingleton
此時單例池singletonObjects中并沒有beanName為a的對象,且并沒有正在創建中,所以返回null
五、AbstractBeanFactory#doGetBean
調用getSingleton方法并傳入beanName+Lambda表達式
六、DefaultSingletonBeanRegistry#getSingleton
- 此時singletonObjects中沒有a
- 標記a正在創建中
- 執行傳入的Lambda表達式,即createBean方法
七、AbstractAutowireCapableBeanFactory#createBean
createBean - doCreateBean
八、AbstractAutowireCapableBeanFactory#doCreateBean
- Bean的實例化
- 可以看到,Bean對象已經創建(A@2126)
- 添加到singletonFactories中(key為beanName,value為ObjectFactory)
九、AbstractAutowireCapableBeanFactory#getEarlyBeanReference
并非將已經實例化但未初始化的Bean對象直接放入singletonFactories(三級緩存)中,考慮到代理對象,所以放入的是Lambda表達式,也就是該方法的執行邏輯
十、DefaultSingletonBeanRegistry#addSingletonFactory
放入singletonFactories(三級緩存)中,key為beanName,value為一個Lambda表達式
執行A的屬性填充(執行過程中發現A依賴B,就去執行B的實例化邏輯)
一、AbstractAutowireCapableBeanFactory#doCreateBean
填充Bean
二、AbstractAutowireCapableBeanFactory#populateBean
- @Autowired注解是通過AutowiredAnnotationBeanPostProcessor解析的
- 這里執行AutowiredAnnotationBeanPostProcessor的postProcessProperties方法
三、AutowiredAnnotationBeanPostProcessor#postProcessProperties
找到A中的b字段需要注入
四、InjectionMetadata#inject
調用AutowiredAnnotationBeanPostProcessor中的inject方法
五、AutowiredAnnotationBeanPostProcessor#inject
調用DefaultListableBeanFactory的resolveDependency方法
六、DefaultListableBeanFactory#resolveDependency
resolveDependency - doResolveDependency
七、DefaultListableBeanFactory#doResolveDependency
- autowiredBeanName:依賴的beanName
- instanceCandidate:依賴的bean類型
八、DependencyDescriptor#resolveCandidate
調用DefaultListableBeanFactory的getBean方法,此時beanName為b,也就是接下來要執行B的實例化、屬性填充、初始化邏輯
執行B的實例化
一、AbstractBeanFactory#getBean
getBean - doGetBean
二、AbstractBeanFactory#doGetBean
此時容器中沒有b對象,返回null
三、AbstractAutowireCapableBeanFactory#createBean
createBean - doCreateBean
四、AbstractAutowireCapableBeanFactory#doCreateBean
- Bean的實例化
- 實例化后的Bean對象和Bean的類型
- 將b和對應的Lambda表達式添加到三級緩存中
- 此時三級緩存中存在a,b兩個元素
- 填充b對象屬性
?
執行B的屬性填充
一、AbstractAutowireCapableBeanFactory#populateBean
同樣的,通過AutowiredAnnotationBeanPostProcessor的postProcessProperties方法中處理@Autowired注解
二、AutowiredAnnotationBeanPostProcessor#postProcessProperties
找到B依賴A
三、InjectionMetadata#inject
執行AutowiredAnnotationBeanPostProcessor的inject方法進行屬性注入
四、AutowiredAnnotationBeanPostProcessor#inject
調用DefaultListableBeanFactory的resolveDependency方法
五、DefaultListableBeanFactory#resolveDependency
resolveDependency - doResolveDependency
六、DefaultListableBeanFactory#doResolveDependency
獲取到注入的beanName和類型,調用DependencyDescriptor的resolveCandidate方法
七、DependencyDescriptor#resolveCandidate
從容器中獲取a對象
八、AbstractBeanFactory#getBean
getBean - doGetBean
九、DefaultSingletonBeanRegistry#getSingleton
此時發生了改變
- 從singletonObjects(一級緩存)中獲取a,沒有
- beanName為a的Bean正在創建
- 從earlySingletonObjects(一級緩存)中獲取a,同樣沒有
- 但是,從三級緩存singletonFactories中獲取a,能獲取到,此時執行三級緩存中a對應的Lambda表達式的邏輯
- 執行Lambda表達式后拿到a對象
- 將a對象(實例化了但未進行初始化)放入二級緩存中
- 刪除三級緩存中的a
?
十、AutowiredAnnotationBeanPostProcessor#inject
通過反射將a對象賦值給b對象的a字段
執行B的初始化
一、AbstractAutowireCapableBeanFactory#doCreateBean
調用initializeBean執行b對象后續的初始化邏輯
二、AbstractAutowireCapableBeanFactory#initializeBean
- Aware接口方法的回調(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)
- BeanPostProcessor的初始化前方法回調
- InitializingBean的afterPropertiesSet方法回調和自定義的初始化方法回調
- BeanPostProcessor的初始化后方法回調
- 返回完成初始化的b對象
三、DefaultSingletonBeanRegistry#getSingleton
- 此時已經執行完b對應的Lambda表達式的doCreateBean的邏輯,拿到的是b已經實例化并初始化好的Bean對象
- 刪除b正在創建的標識
- 將b添加到一級緩存singletonObjects單例池中,刪除三級緩存和二級緩存中的b
- 返回已經實例化并初始化好的b對象
執行A的屬性填充(此時依賴的B已經完成了實例化和初始化放到容器的單例池中,接著執行之前沒有執行完成的A的屬性填充邏輯)
一、AutowireAnnotationBeanPostProcessor#inject
通過反射將b對象賦值給a對象的b字段(b對象中的a字段此時的值為完成了實例化但未進行初始化的a對象,沒有進行初始化的對象并不影響別的對象去引用,后續對a對象進行初始化即可)
執行A的初始化
一、AbstractAutowireCapableBeanFactory#doCreateBean
執行a對象的初始化邏輯
二、DefaultSingletonBeanRegistry#getSingleton
執行完a對象的初始化邏輯,將a添加到一級緩存singletonObjects中,刪除三級緩存和二級緩存中的a,至此完成了相互引用的a和b對象的實例化和初始化邏輯,并將它們放入了容器的單例池中