首先,我們在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 }