3.2spring源碼系列----循環依賴源碼分析


首先,我們在3.1 spring5源碼系列--循環依賴 之 手寫代碼模擬spring循環依賴 中手寫了循環依賴的實現. 這個實現就是模擬的spring的循環依賴. 目的是為了更容易理解spring源碼.

下面我們就進入正題, 看看spring的循環依賴源碼.

 

一、getBean整體流程

 

目標很明確了, 就是要看看spring如何解決循環依賴的. 

代碼入口是refresh()#finishBeanFactoryInitialization(beanFactory);

二、拆解研究流程中的每一步

調用方法beanFactory.preInstantiateSingletons();實例化剩余的單例bean. 為什么是剩余的?很顯然我們在上面已經實例化一部分了.比如配置類, postProcessor等.

2.1 入口

1 @Override
 2     public void preInstantiateSingletons() throws BeansException {
 3         if (logger.isTraceEnabled()) {
 4             logger.trace("Pre-instantiating singletons in " + this);
 5         }
 6 
 7 
 8         // 獲取容器中所有bean定義的名字
 9         List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
10 
11         // Trigger initialization of all non-lazy singleton beans...
12         /**
13          * 第一步: 循環bean定義的name
14          */
15         for (String beanName : beanNames) {
16             // 獲取bean定義
17             RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
18             // 生產bean定義的條件: 不是抽象的, 是單例的, 不是懶加載的. 符合這個標准的, 最后才會調用getBean()生產bean
19             if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
20                 // 這里判斷是不是工廠bean, 這里和BeanFactory不是一個意思, 判斷當前這個bean是否實現了beanFactory的接口
21                 if (isFactoryBean(beanName)) {
22                     Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
23                     if (bean instanceof FactoryBean) {
24                         final FactoryBean<?> factory = (FactoryBean<?>) bean;
25                         boolean isEagerInit;
26                         if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
27                             isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
28                                             ((SmartFactoryBean<?>) factory)::isEagerInit,
29                                     getAccessControlContext());
30                         }
31                         else {
32                             isEagerInit = (factory instanceof SmartFactoryBean &&
33                                     ((SmartFactoryBean<?>) factory).isEagerInit());
34                         }
35                         if (isEagerInit) {
36                             // 獲取bean
37                             getBean(beanName);
38                         }
39                     }
40                 }
41                 else {
              // 第二步: 調用bean定義
42                     getBean(beanName);
43                 }
44             }
45         }
46 
47         // Trigger post-initialization callback for all applicable beans...
48         
51         for (String beanName : beanNames) {
52             // 從緩存中得到實例instance
53             Object singletonInstance = getSingleton(beanName);
54             if (singletonInstance instanceof SmartInitializingSingleton) {
55                 final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
56                 if (System.getSecurityManager() != null) {
57                     AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
58                         smartSingleton.afterSingletonsInstantiated();
59                         return null;
60                     }, getAccessControlContext());
61                 }
62                 else {
63                     smartSingleton.afterSingletonsInstantiated();
64                 }
65             }
66         }
67     }

 

首先, 循環bean定義, 這和我們模擬spring循環的第一步是一樣的. 

第二步: 判斷從BeanDefinitionMap中取出來的這個bean是否滿足生產bean的條件

我們注意代碼注釋中, 生產bean定義的條件: 不是抽象的, 是單例的, 不是懶加載的. 符合這個標准的, 最后才會調用getBean()生產bean

然后:調用getBean()

到目前為止,我們完成了上圖源碼圖的第一部分:

 

 

 2.2 創建bean前的准備工作

接下來看看getBean().doGetBean()方法

 

1 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
  2             @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  3 
  4         // 第一步: 轉換bean name. 在這里傳入進來的name可能是別名, 也有可能是工廠bean的name, 所以在這里進行一個轉換
  5         final String beanName = transformedBeanName(name);
  6         Object bean;
  7 
  8         // Eagerly check singleton cache for manually registered singletons.
  9         // 第二步: 嘗試去緩存中獲取對象, 如果沒有獲取到就創建bean
 10         Object sharedInstance = getSingleton(beanName);
 11         if (sharedInstance != null && args == null) {
 12             if (logger.isTraceEnabled()) {
 13                 //判斷當前類是否是正在創建中
 14                 if (isSingletonCurrentlyInCreation(beanName)) {
 15                     logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
 16                             "' that is not fully initialized yet - a consequence of a circular reference");
 17                 }
 18                 else {
 19                     logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
 20                 }
 21             }
 22             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 23         }
 24 
 25         else {
 26             // Fail if we're already creating this bean instance:
 27             // We're assumably within a circular reference.
 28             /**
 29              * 判斷當前的bean是不是多例, 如果是這拋出異常
 30              *
 31              * 判斷當前這個bean是不是多例bean. 如果配置了@Scope("prototype") 就表示這是一個多例的bean
 32              * spring 只能解決單例對象的setter注入的循環依賴, 不能解決構造器注入
 33              *
 34              * 如果是多例的bean, 當前正在創建bean, 也會拋出異常---這也是循環依賴的問題
 35              */
 36             if (isPrototypeCurrentlyInCreation(beanName)) {
 37                 throw new BeanCurrentlyInCreationException(beanName);
 38             }
 39 
 40             /**
 41              * 下面這段代碼是關於子父容器的, 只有spring mvc繼承自spring, 才會有子父容器的問題.
 42              */
 43             // Check if bean definition exists in this factory.
 44             BeanFactory parentBeanFactory = getParentBeanFactory();
 45             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 46                 // Not found -> check parent.
 47                 String nameToLookup = originalBeanName(name);
 48                 if (parentBeanFactory instanceof AbstractBeanFactory) {
 49                     return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
 50                             nameToLookup, requiredType, args, typeCheckOnly);
 51                 }
 52                 else if (args != null) {
 53                     // Delegation to parent with explicit args.
 54                     return (T) parentBeanFactory.getBean(nameToLookup, args);
 55                 }
 56                 else if (requiredType != null) {
 57                     // No args -> delegate to standard getBean method.
 58                     return parentBeanFactory.getBean(nameToLookup, requiredType);
 59                 }
 60                 else {
 61                     return (T) parentBeanFactory.getBean(nameToLookup);
 62                 }
 63             }
 64 
 65             /**
 66              * 方法參數typeCheckOnly是用來判斷#getBean()方法時, 表示是否為僅僅進行類型檢查,
 67              * 如果不僅僅做類型檢查, 而是創建bean對象, 則需要調用#markBeanAsCreated(String name)
 68              *
 69              */
 70             if (!typeCheckOnly) {
 71                 markBeanAsCreated(beanName);
 72             }
 73 
 74             try {
 75                 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 76                 checkMergedBeanDefinition(mbd, beanName, args);
 77 
 78                 // Guarantee initialization of beans that the current bean depends on.
 79                 /**
 80                  * 現在有兩個bean1, bean2 , 加載的時候調用的是bean1, bean2. 但如果我們想要bean2優先加載, 就使用@DependOn注解
 81                  * 用來解析帶有dependOn注解的類
 82                  */
 83                 String[] dependsOn = mbd.getDependsOn();
 84                 if (dependsOn != null) {
 85                     for (String dep : dependsOn) {
 86                         if (isDependent(beanName, dep)) {
 87                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 88                                     "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 89                         }
 90                         registerDependentBean(dep, beanName);
 91                         try {
 92                             getBean(dep);
 93                         }
 94                         catch (NoSuchBeanDefinitionException ex) {
 95                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 96                                     "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
 97                         }
 98                     }
 99                 }
100 
101                 // Create bean instance.
102                 /**
103                  * 第三步: 創建單例bean實例
104                  */
105                 if (mbd.isSingleton()) { // 處理單例bean
106                     /**
107                      * 這里getSingleton()和上面的getSigleton不一樣, 上面的是從一級緩存中拿.
108                      * 這個getSingleton()就辦了一件事: 將bean設置為正在創建的狀態. 這個狀態很重要, 如果出現循環依賴, 發現bean正在創建, 就不會再創建了
109                      */
110                     sharedInstance = getSingleton(beanName, () -> {
111                         try {
112                             return createBean(beanName, mbd, args);
113                         }
114                         catch (BeansException ex) {
115                             // Explicitly remove instance from singleton cache: It might have been put there
116                             // eagerly by the creation process, to allow for circular reference resolution.
117                             // Also remove any beans that received a temporary reference to the bean.
118                             destroySingleton(beanName);
119                             throw ex;
120                         }
121                     });
122                     // 得到bean實例對象
123                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124                 }
125 
126                 else if (mbd.isPrototype()) { // 處理多例bean
127                     // It's a prototype -> create a new instance.
128                     Object prototypeInstance = null;
129                     try {
130                         // 當前正在創建多例bean
131                         beforePrototypeCreation(beanName);
132                         // 執行創建bean
133                         prototypeInstance = createBean(beanName, mbd, args);
134                     }
135                     finally {
136                         afterPrototypeCreation(beanName);
137                     }
138                     // 獲取bean實例對象
139                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
140                 }
141 
142                 else { // 處理其他類型的bean
143                     String scopeName = mbd.getScope();
144                     final Scope scope = this.scopes.get(scopeName);
145                     if (scope == null) {
146                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
147                     }
148                     try {
149                         Object scopedInstance = scope.get(beanName, () -> {
150                             beforePrototypeCreation(beanName);
151                             try {
152                                 return createBean(beanName, mbd, args);
153                             }
154                             finally {
155                                 afterPrototypeCreation(beanName);
156                             }
157                         });
158                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
159                     }
160                     catch (IllegalStateException ex) {
161                         throw new BeanCreationException(beanName,
162                                 "Scope '" + scopeName + "' is not active for the current thread; consider " +
163                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
164                                 ex);
165                     }
166                 }
167             }
168             catch (BeansException ex) {
169                 cleanupAfterBeanCreationFailure(beanName);
170                 throw ex;
171             }
172         } 

 

在這里, 首先從緩存中獲取bean, 看緩存中是否已經存在了

 Object sharedInstance = getSingleton(beanName);

然后, 如果緩存中已經存在了,那么久直接取出來. 代碼如下: 

    if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) {
                //判斷當前bean是否是正在創建中(單例bean)
                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 + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

 

如果是空, 就說明是第一次創建, 執行else的部分

首先, 判斷是否是正在創建的多例bean, 如果是正在創建的多例bean, 就拋出異常,

  已經是正在創建了, 說明這至少是第二次了, 這里處理的是單例bean的循環依賴, 不處理多例bean的循環依賴, 所以拋出異常

  對應的代碼是這一句

  

// Fail if we're already creating this bean instance:
 27             // We're assumably within a circular reference.
 28             /**
 29              * 判斷當前的bean是不是多例, 如果是這拋出異常
 30              *
 31              * 判斷當前這個bean是不是多例bean. 如果配置了@Scope("prototype") 就表示這是一個多例的bean
 32              * spring 只能解決單例對象的setter注入的循環依賴, 不能解決構造器注入
 33              *
 34              * 如果是多例的bean, 當前正在創建bean, 也會拋出異常---這也是循環依賴的問題
 35              */
 36             if (isPrototypeCurrentlyInCreation(beanName)) {
 37                 throw new BeanCurrentlyInCreationException(beanName);
 38             }

那么, 接下來就是首次創建bean. 首次創建的bean有三種情況:

  第一種, 這個bean是單例的.

  第二種, 這個bean是多例的.

  第三種. 其他類型

對應的代碼就是這一塊. 有行號, 可以和上面一一對應上

// Create bean instance.
102                 /**
103                  * 第三步: 創建單例bean實例
104                  */
105                 if (mbd.isSingleton()) { // 處理單例bean
106                     /**
107                      * 這里getSingleton()和上面的getSigleton不一樣, 上面的是從一級緩存中拿.
108                      * 這個getSingleton()就辦了一件事: 將bean設置為正在創建的狀態. 這個狀態很重要, 如果出現循環依賴, 發現bean正在創建, 就不會再創建了
109                      */
110                     sharedInstance = getSingleton(beanName, () -> {
111                         try {
112                             return createBean(beanName, mbd, args);
113                         }
114                         catch (BeansException ex) {
115                             // Explicitly remove instance from singleton cache: It might have been put there
116                             // eagerly by the creation process, to allow for circular reference resolution.
117                             // Also remove any beans that received a temporary reference to the bean.
118                             destroySingleton(beanName);
119                             throw ex;
120                         }
121                     });
122                     // 得到bean實例對象
123                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124                 }
125 
126                 else if (mbd.isPrototype()) { // 處理多例bean
127                     // It's a prototype -> create a new instance.
128                     Object prototypeInstance = null;
129                     try {
130                         // 當前正在創建多例bean
131                         beforePrototypeCreation(beanName);
132                         // 執行創建bean
133                         prototypeInstance = createBean(beanName, mbd, args);
134                     }
135                     finally {
136                         afterPrototypeCreation(beanName);
137                     }
138                     // 獲取bean實例對象
139                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
140                 }
141 
142                 else { // 處理其他類型的bean
143                     String scopeName = mbd.getScope();
144                     final Scope scope = this.scopes.get(scopeName);
145                     if (scope == null) {
146                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
147                     }
148                     try {
149                         Object scopedInstance = scope.get(beanName, () -> {
150                             beforePrototypeCreation(beanName);
151                             try {
152                                 return createBean(beanName, mbd, args);
153                             }
154                             finally {
155                                 afterPrototypeCreation(beanName);
156                             }
157                         });
158                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
159                     }
160                     catch (IllegalStateException ex) {
161                         throw new BeanCreationException(beanName,
162                                 "Scope '" + scopeName + "' is not active for the current thread; consider " +
163                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
164                                 ex);
165                     }
166                 }

 

我們的重點研究對象是單例bean. 所以,重點看單例bean的實現

105                 if (mbd.isSingleton()) { // 處理單例bean
106                     /**
107                      * 這里getSingleton()和上面的getSigleton不一樣, 上面的是從一級緩存中拿.
108                      * 這個getSingleton()就辦了一件事: 將bean設置為正在創建的狀態. 這個狀態很重要, 如果出現循環依賴, 發現bean正在創建, 就不會再創建了
109                      */
110                     sharedInstance = getSingleton(beanName, () -> { 111 try { 112 return createBean(beanName, mbd, args); 113 } 114 catch (BeansException ex) { 115 // Explicitly remove instance from singleton cache: It might have been put there 116 // eagerly by the creation process, to allow for circular reference resolution. 117 // Also remove any beans that received a temporary reference to the bean. 118 destroySingleton(beanName); 119 throw ex; 120 } 121 }); 122                     // 得到bean實例對象
123                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 124                 }

 

這里的重點是調用了getSingleton(beanName, FactoryObject); FactoryObject是一個接口. 定義了一個鈎子方法getObject(). 

這個接口在這里這是進行了定義, 並不會執行. 什么時候執行呢? 后面調用的時候執行. 

下面來看看getSingleton()方法, 鈎子方法也是在這里被調用的.

 1 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
 2         Assert.notNull(beanName, "Bean name must not be null");
 3         synchronized (this.singletonObjects) {
 4             // 第一步: 從一級緩存中獲取單例對象
 5             Object singletonObject = this.singletonObjects.get(beanName);
 6             if (singletonObject == null) {
 7                 if (this.singletonsCurrentlyInDestruction) {
 8                     throw new BeanCreationNotAllowedException(beanName,
 9                             "Singleton bean creation not allowed while singletons of this factory are in destruction " +
10                             "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
11                 }
12                 if (logger.isDebugEnabled()) {
13                     logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
14                 }
15                 // 第二步: 將bean添加到singletonsCurrentlyInCreation中, 表示bean正在創建
16                 beforeSingletonCreation(beanName);
17                 boolean newSingleton = false;
18                 boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
19                 if (recordSuppressedExceptions) {
20                     this.suppressedExceptions = new LinkedHashSet<>();
21                 }
22                 try {
23                     // 第三步: 這里調用getObject()鈎子方法, 就會回調匿名函數, 調用singletonFactory的createBean()
24                     singletonObject = singletonFactory.getObject();
25                     newSingleton = true;
26                 }
27                 catch (IllegalStateException ex) {
28                     // Has the singleton object implicitly appeared in the meantime ->
29                     // if yes, proceed with it since the exception indicates that state.
30                     singletonObject = this.singletonObjects.get(beanName);
31                     if (singletonObject == null) {
32                         throw ex;
33                     }
34                 }
35                 catch (BeanCreationException ex) {
36                     if (recordSuppressedExceptions) {
37                         for (Exception suppressedException : this.suppressedExceptions) {
38                             ex.addRelatedCause(suppressedException);
39                         }
40                     }
41                     throw ex;
42                 }
43                 finally {
44                     if (recordSuppressedExceptions) {
45                         this.suppressedExceptions = null;
46                     }
47                     afterSingletonCreation(beanName);
48                 }
49                 if (newSingleton) {
50                     addSingleton(beanName, singletonObject);
51                 }
52             }
53             return singletonObject;
54         }
55     }

 

這里是調用getBean().

第一步: 去一級緩存中取成熟的單例bean. 如果拿到了, 就直接返回. 如果沒拿到. 那么執行創建. 

第二步: 在創建之前, 先把這個bean放入到正在創建的單例bean集合中. 標記這個bean正在創建中

第三步: 就是調用鈎子方法getObject()了. 這個方法的方法體是在上面定義的. 其內容是去創建實例

            sharedInstance = getSingleton(beanName, () -> {
                        try {
                            // 這里定義了一個鈎子函數. 此時只是定義, 並不執行. 在真正需要創建bean的地方才會執行 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;
                        }
                    });

 

這里的代碼邏輯是完成了創建之前的邏輯

2.3 創建bean 

下面看看創建bean的過程

  1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
  2             throws BeanCreationException {
  3 
  4         // Instantiate the bean.
  5         BeanWrapper instanceWrapper = null;
  6         if (mbd.isSingleton()) {
  7             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  8         }
  9         if (instanceWrapper == null) {
 10             /**
 11              * 第一步: 實例化  12              * 這里面的調用鏈非常深, 后面再看
 13              * bean實例化有兩種方式
 14              * 1. 使用反射:  使用反射也有兩種方式,
 15              *         a. 通過無參構造函數 (默認的方式)
 16              *             從beanDefinition中可以得到beanClass,
 17              *             ClassName = BeanDefinition.beanClass
 18              *             Class clazz = Class.forName(ClassName);
 19              *             clazz.newInstance();
 20              *             這樣就可以實例化bean了
 21              *
 22              *         b. 通過有參函數.
 23              *            ClassName = BeanDefinition.beanClass
 24              *             Class clazz = Class.forName(ClassName);
 25              *             Constractor con = class.getConstractor(args....)
 26              *             con.newInstance();
 27              *
 28              * 2. 使用工廠
 29              *         我們使用@Bean的方式, 就是使用的工廠模式, 自己控制實例化過程
 30              *
 31              */
 32             instanceWrapper = createBeanInstance(beanName, mbd, args);
 33         }
 34         // 這里使用了裝飾器的設計模式
 35         final Object bean = instanceWrapper.getWrappedInstance();
 36         Class<?> beanType = instanceWrapper.getWrappedClass();
 37         if (beanType != NullBean.class) {
 38             mbd.resolvedTargetType = beanType;
 39         }
 40 
 41         // Allow post-processors to modify the merged bean definition.
 42         // 允許后置處理器修改已經合並的beanDefinition
 43         synchronized (mbd.postProcessingLock) {
 44             if (!mbd.postProcessed) {
 45                 try {
 46                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
 47                 }
 48                 catch (Throwable ex) {
 49                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 50                             "Post-processing of merged bean definition failed", ex);
 51                 }
 52                 mbd.postProcessed = true;
 53             }
 54         }
 55 
 56         /**
 57          * 緩存單例bean到三級緩存中, 以防止循環依賴
 58          * 判斷是否是早期引用的bean, 如果是, 則允許提前暴露引用
 59      *
 60          * 判斷是否能夠早起暴露的條件  61          *     1. 是單例
 62          *     2. 允許循環依賴
 63          *     3. 正在創建的bean
 64          */
 65         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
 66  isSingletonCurrentlyInCreation(beanName));  67         if (earlySingletonExposure) {
 68             if (logger.isTraceEnabled()) {
 69                 logger.trace("Eagerly caching bean '" + beanName +
 70                         "' to allow for resolving potential circular references");
 71             }
 72             // 把我們的早期對象包裝成一個singletonFactory對象, 該對象提供了getObject()方法, 把靜態的bean放到三級緩存中去了.
 73             addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
 74         }
 75 
 76         // Initialize the bean instance.
 77         Object exposedObject = bean;
 78         try {
 79             // 第二步:填充屬性, 給屬性賦值(調用set方法) 這里也是調用的后置處理器
 80             populateBean(beanName, mbd, instanceWrapper);
 81             // 第三步: 初始化.
 82             exposedObject = initializeBean(beanName, exposedObject, mbd);
 83         }
 84         catch (Throwable ex) {
 85             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
 86                 throw (BeanCreationException) ex;
 87             }
 88             else {
 89                 throw new BeanCreationException(
 90                         mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
 91             }
 92         }
 93 
 94         /**
 95          * 初始化完成以后, 判斷是否是早期的對象  96          * 是循環依賴. 才會走進這里來
 97           */
 98         if (earlySingletonExposure) {
 99             // 去緩存中獲取到我們的對象 由於傳遞的allowEarlyReference是false, 要求只能在一級二級緩存中取
100             // 正常的普通的bean(不存在循環依賴的bean) 創建的過程中, 不會把三級緩存提升到二級緩存中.
101             Object earlySingletonReference = getSingleton(beanName, false);
102             if (earlySingletonReference != null) {
103                 if (exposedObject == bean) {
104                     exposedObject = earlySingletonReference;
105                 }
106                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
107                     String[] dependentBeans = getDependentBeans(beanName);
108                     Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
109                     for (String dependentBean : dependentBeans) {
110                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
111                             actualDependentBeans.add(dependentBean);
112                         }
113                     }
114                     if (!actualDependentBeans.isEmpty()) {
115                         throw new BeanCurrentlyInCreationException(beanName,
116                                 "Bean with name '" + beanName + "' has been injected into other beans [" +
117                                 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
118                                 "] in its raw version as part of a circular reference, but has eventually been " +
119                                 "wrapped. This means that said other beans do not use the final version of the " +
120                                 "bean. This is often the result of over-eager type matching - consider using " +
121                                 "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
122                     }
123                 }
124             }
125         }
126 
127         // Register bean as disposable.
128         try {
129             registerDisposableBeanIfNecessary(beanName, bean, mbd);
130         }
131         catch (BeanDefinitionValidationException ex) {
132             throw new BeanCreationException(
133                     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
134         }
135 
136         return exposedObject;
137     }

 

首先, 實例化bean, 實例化的方式有兩種. 一種是通過反射, 另一種是通過動態

 1        /**
 2              * 第一步: 實例化  3              * 這里面的調用鏈非常深, 后面再看
 4              * bean實例化有兩種方式
 5              * 1. 使用反射:  使用反射也有兩種方式,
 6              *         a. 通過無參構造函數 (默認的方式)
 7              *             從beanDefinition中可以得到beanClass,
 8              *             ClassName = BeanDefinition.beanClass
 9              *             Class clazz = Class.forName(ClassName);
10              *             clazz.newInstance();
11              *             這樣就可以實例化bean了
12              *
13              *         b. 通過有參函數.
14              *            ClassName = BeanDefinition.beanClass
15              *             Class clazz = Class.forName(ClassName);
16              *             Constractor con = class.getConstractor(args....)
17              *             con.newInstance();
18              *
19              * 2. 使用工廠 20              *         我們使用@Bean的方式, 就是使用的工廠模式, 自己控制實例化過程
21              *
22              */
23             instanceWrapper = createBeanInstance(beanName, mbd, args);

 

判斷是否是早期暴露的bean. 滿足早期暴露的bean的三個條件是

1. 是單例的

2. 允許循環依賴

3. bean已經是處在正在創建中的行列了.

     /* 判斷是否能夠早起暴露的條件
         *     1. 是單例
         *     2. 允許循環依賴
         *     3. 正在創建的bean
         */
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));    

 

創建bean的第二步: 屬性賦值

// 第二步:填充屬性, 給屬性賦值(調用set方法)  這里也是調用的后置處理器
populateBean(beanName, mbd, instanceWrapper);

在這里會判斷, 是否帶有@Autowired的屬性. 分為兩種一種是Name,一種是Type

@SuppressWarnings("deprecation")  // for postProcessPropertyValues
    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        if (bw == null) {
            if (mbd.hasPropertyValues()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                // Skip property population phase for null instance.
                return;
            }
        }

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
        // state of the bean before properties are set. This can be used, for example,
        // to support styles of field injection.
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        return;
                    }
                }
            }
        }

        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

        // 判斷屬性是否有Autowired注解
        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
        // Autowired是根據名字或者根據類型
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; }

        ......
    }

 

如果按照名字注入

 1 protected void autowireByName(
 2             String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
 3 
 4         String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
 5         for (String propertyName : propertyNames) {
 6             if (containsBean(propertyName)) {
 7                 // 調用getBean 8 Object bean = getBean(propertyName);  9                 pvs.add(propertyName, bean);
10                 registerDependentBean(propertyName, beanName);
11                 if (logger.isTraceEnabled()) {
12                     logger.trace("Added autowiring by name from bean name '" + beanName +
13                             "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
14                 }
15             }
16             else {
17                 if (logger.isTraceEnabled()) {
18                     logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
19                             "' by name: no matching bean found");
20                 }
21             }
22         }
23     }

 

會再次調用getBean方法. 構建bean. 這是就有可能出現循環依賴了. 

按類型注入也是一樣的. 

只是解析bean的方式不同.

 

創建bean的第三步: 初始化

 // 第三步: 初始化.
 exposedObject = initializeBean(beanName, exposedObject, mbd);

在初始化bean的時候, 會調用很多的aware. 還會調用init-method方法. 以及bean的后置處理器.

 

第四步:刪除實例化和靜態方法在緩存中的數據

/**
         * 初始化完成以后, 判斷是否是早期的對象
         * 是循環依賴. 才會走進這里來
          */
        if (earlySingletonExposure) {
            // 去緩存中獲取到我們的對象 由於傳遞的allowEarlyReference是false, 要求只能在一級二級緩存中取
            // 正常的普通的bean(不存在循環依賴的bean) 創建的過程中, 不會把三級緩存提升到二級緩存中.
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                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 " +
                                "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

 

removeSingletonIfCreatedForTypeCheckOnly調用方法, 刪除緩存.

這既是getBean()整個的過程. 中間還有很多細節, 沒有往里面深入的看, 因為spring代碼非常的深, 看的太深就忘了我們的目標了. 結合之前手寫的spring循環依賴的思想看, 還是可以看得懂的. 

 

 

三. 接下來有幾個問題

問題1: 為什么需要二級緩存和三級緩存?

一級緩存: 用來存儲完整的bean

二級緩存: 用來存儲早期的,純凈的bean, 也就是沒有注入屬性的bean

三級緩存: 存的是函數的接口, 主要目的是為了解耦

 二級緩存 和三級緩存 結合起來, 解決了循環依賴下的AOP動態代理的問題

問題2:有沒有解決構造函數的循環依賴

答案是沒有. 因為構造函數是在實例化的時候構建的. 這個時候bean都還沒有創建, 所以沒有辦法處理循環依賴.如果出現構造函數的循環依賴, 是會直接報錯的..

 

問題3:有沒有解決多例下的循環依賴

也是沒有的, 因為我們會判斷, 如果是多例, 那么會拋出異常

 1             /**
 2              * 第二步: 判斷當前bean是否是正在創建中的多例bean, 如果是就拋出異常
 3              *
 4              * 2. 判斷當前這個bean是不是多例bean. 如果配置了@Scope("prototype") 就表示這是一個多例的bean
 5              * spring 只能解決單例對象的setter注入的循環依賴, 不能解決構造器注入
 6              *
 7              * 如果是多例的bean, 當前正在創建bean, 也會拋出異常---這也是循環依賴的問題
 8              */
 9             if (isPrototypeCurrentlyInCreation(beanName)) {
10                 throw new BeanCurrentlyInCreationException(beanName);
11             }   

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM