本文結合《Spring源碼深度解析》來分析Spring 5.0.6版本的源代碼。若有描述錯誤之處,歡迎指正。
目錄
一、創建bean的實例
1. autowireConstructor
2 . instantiateBean
3 . 實例化策略
二、記錄創建bean的ObjectFactory
三、屬性注入
1. autowireByName
2. autowireByType
3. applyPropertyValues
四、初始化bean
1. 激活 Aware 方法
2. 處理器的應用
3. 激活自定義的 init 方法
五、注冊 DisposableBean
介紹了循環依賴以及Spring中的循環依賴的處理方式后,我們繼續Spring源碼分析(十六)准備創建bean的內容。當經歷過resolveBeforelnstantiation方法后,程序有兩個選擇,如果創建了代理或者說重寫了InstantiationAwareBeanPostProcessor的postProcessBeforelnstantiation方法並在方法postProcessBeforelnstantiation中改變了 bean,則直接返回就可以了,否則需要進行常規bean的創建。而 這常規bean的創建就是在doCreateBean中完成的。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 根據指定bean使用對應的策略創建新的實例,如:工廠方法、構造函數自動注人、簡單初始化 instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { // 應用MergedBeanDefinitionPostProcessor applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. // 是否需要提早曝光:單例 & 允許循環依賴 & 當前bean正在創建中,檢測循環依賴 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } // 為避免后期循環依賴,可以在bean初始化完成前將創建實例的ObjectFactory加入工廠 /** * getEarlyBeanReference(beanName, mbd, bean)方法: * 對bean再一次依賴引用,主要應用SmartInstantiationAwareBeanPostProcessor * 其中我們熟知的AOP就是在這里將advice動態織入bean中,若沒有則直接返回bean,不做任何處理 */ addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // 對bean進行填充,將各個屬性值注入,其中,可能存在依賴於其他bean的屬性,則會遞歸初始依賴bean populateBean(beanName, mbd, instanceWrapper); // 調用初始化方法,比如init-method exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); // earlySingletonReference只有在檢測到有循環依賴的情況下才會不為空 if (earlySingletonReference != null) { // 如果exposedObject沒有在初始化方法中被改變,也就是沒有被增強 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); } } /** * 因為bean創建后其所依賴的bean一定是已經創建的,actualDependentBeans不為空則表示當前bean創建后 * 其依賴的bean卻沒有全部創建完,也就是說存在循環依賴 */ 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 " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. try { // 根據scope注冊bean registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
盡管日志與異常的內容非常重要,但是在閱讀源碼的時候似乎大部分人都會直接忽略掉。在此不深入探討日志及異常的設計,我們看看整個函數的概要思路。
(1)如果是單例則需要首先清除緩存 。
(2)實例化 bean , 將 BeanDefinition 轉換為 BeanWrapper 。轉換是一個復雜的過程,但是我們可以嘗試概括大致的功能,如下所示。
- 如果存在工廠方法則使用工廠方法進行初始化。
- 一個類有多個構造函數,每個構造函數都有不同的參數,所以需要根據參數鎖定構造函數並進行初始化。
- 如果既不存在工廠方法也不存在帶有參數的構造函數,則使用默認的構造函數進行 bean 的實例化。
(3)MergedBeanDefinitionPostProcessor的應用。
bean合並后的處理, Autowired 注解正是通過此方法實現諸如類型的預解析。
(4)依賴處理。
在 Spring 中會有循環依賴的情況,例如,當 A 中含有 B 的屬性,而 B 中又含有 A 的屬性時就會構成一個循環依賴,此時如果 A 和 B 都是單例,那么在 Spring 中的處理方式就是當創建 B 的時候,涉及自動注人 A 的步驟時,並不是直接去再次創建 A ,而是通過放入緩存中的ObjectFactory來創建實例,這樣就解決了循環依賴的問題。
(5)屬性填充。
將所有屬性填充至 bean 的實例中。
(6)循環依賴檢查。
之前有提到過,在 Sping 中解決循環依賴只對單例有效,而對於 prototype 的 bean , spring 沒有好的解決辦法,唯一要做的就是拋出異常。在這個步驟里面會檢測已經加載的 bean 是否已經出現了依賴循環,並判斷是否需要拋出異常。
(7)注冊 DisposableBean 。
如果配置了 dcstroy-method ,這里需要注冊以便一於在銷毀時候調用。
(8)完成創建並返回。
可以看到上面的步驟非常的繁瑣,每一步驟都使用了大量的代碼來完成其功能,最復雜也是最難以理解的當屬循環依賴的處理,在真正進人 doCreateBcan 前我們有必要先了解下循環依賴。
一、創建bean的實例
當我們了解了循環依賴以后就可以深入分析創建 bean 的每個步驟了,首先我們從 createBeanlnstance 開始。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. // 解析class Class<?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } // 如果工廠方法不為空則使用工廠方法初始化策略 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // Shortcut when re-creating the same bean... boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { // 一個類有多個構造函數,每個構造函數都有不同的參數,所以調用前需要先根據參數鎖定構造函數或對應的工廠方法 if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } // 如果已經解析過則使用解析好的構造函數 if (resolved) { if (autowireNecessary) { // 構造函數自動注入 return autowireConstructor(beanName, mbd, null, null); } else { // 使用默認構造函數構造 return instantiateBean(beanName, mbd); } } // Need to determine the constructor... // 需要根據參數解析構造函數 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { // 構造函數自動注入 return autowireConstructor(beanName, mbd, ctors, args); } // No special handling: simply use no-arg constructor. // 使用默認構造函數構造 return instantiateBean(beanName, mbd); }
雖然代碼中實例化的細節非常復雜,但是在 CreateBeanlntance 方法中我們還是可以清晰地看到實例化的邏輯的。
(1)如果在 RootBeanDefinition 中存在 factoryMethodName 屬性,或者說在配置文件中配置了 factory-method,那么 Spring會嘗試使用instantiateUsingFactoryMethod(beanName, mbd, args)方法根據 RootBeanDefinition 中的配置生成 bean 的實例。
(2)解析構造函數並進行構造函數的實例化。因為一個 bean 對應的類中可能會有多個構造函數,而每個構造函數的參數不同, Spring 在根據參數及類型去判斷最終會使用哪個構造函數進行實例化。但是,判斷的過程是個比較消耗性能的步驟,所以采用緩存機制,如果已經解析過則不需要重復解析而是直接從RootBeanDefinition中的屬性resolvedConstructorOrFactoryMethod緩存的值去取,否則需要再次解析,並將解析的結果添加至RootBeanDefinition中的屬性resolvedConstructorOrFactoryMethod中。
1. autowireConstructor
對於實例的創建Spring中分成了兩種情況,一種是通用的實例化,另一種是帶有參數的實例化。帶有參數的實例化過程相當復雜,因為存在這不確定性,所以在判斷對應參數上做了大量工作。
public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) { BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw); Constructor<?> constructorToUse = null; ArgumentsHolder argsHolderToUse = null; Object[] argsToUse = null; // explicitArgs通過getBean方法傳入 // 如果getBean方法調用的時候指定方法參數,那么直接使用 if (explicitArgs != null) { argsToUse = explicitArgs; } else { // 如果在getBean方法調用的時候沒有指定則嘗試從配置文件中解析 Object[] argsToResolve = null; // 嘗試從緩存中獲取 synchronized (mbd.constructorArgumentLock) { constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; if (constructorToUse != null && mbd.constructorArgumentsResolved) { // Found a cached constructor... // 從緩存中取 argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { // 配置的構造函數參數 argsToResolve = mbd.preparedConstructorArguments; } } } // 如果緩存中存在 if (argsToResolve != null) { // 解析參數類型,如給定方法的構造函數A(int, int)則通過此方法后就會把配置中的("1", "1")轉換為(1, 1) // 緩存中的值可能是原始值也可能是最終值 argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true); } } // 沒有被緩存 if (constructorToUse == null) { // Need to resolve the constructor. boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); ConstructorArgumentValues resolvedValues = null; int minNrOfArgs; if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { // 提取配置文件中的配置的構造函數參數 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); // 用於承載解析后的構造函數參數的值 resolvedValues = new ConstructorArgumentValues(); // 能解析到的參數個數 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); } // Take specified constructors, if any. Constructor<?>[] candidates = chosenCtors; if (candidates == null) { Class<?> beanClass = mbd.getBeanClass(); try { candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors()); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() + "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex); } } // 排序給定的構造函數,public構造函數優先參數數量降序、非public構造函數參數數量降序 AutowireUtils.sortConstructors(candidates); int minTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<?>> ambiguousConstructors = null; LinkedList<UnsatisfiedDependencyException> causes = null; for (Constructor<?> candidate : candidates) { Class<?>[] paramTypes = candidate.getParameterTypes(); if (constructorToUse != null && argsToUse.length > paramTypes.length) { // 如果已經找到選用的構造函數或者需要的參數個數小於當前的構造函數參數個數則終止,因為已經按照參數個數降序排列 // Already found greedy constructor that can be satisfied -> // do not look any further, there are only less greedy constructors left. break; } if (paramTypes.length < minNrOfArgs) { // 參數個數不相等 continue; } ArgumentsHolder argsHolder; if (resolvedValues != null) { // 有參數則根據值構造對應參數類型的參數 try { // 注釋上獲取參數名稱 String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length); if (paramNames == null) { // 獲取參數名稱探索器 ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { // 獲取指定構造函數的參數名稱 paramNames = pnd.getParameterNames(candidate); } } // 根據名稱和數據類型創建參數持有者 argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1); } catch (UnsatisfiedDependencyException ex) { if (logger.isTraceEnabled()) { logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex); } // Swallow and try next constructor. if (causes == null) { causes = new LinkedList<>(); } causes.add(ex); continue; } } else { // Explicit arguments given -> arguments length must match exactly. if (paramTypes.length != explicitArgs.length) { continue; } // 構造函數沒有參數的情況 argsHolder = new ArgumentsHolder(explicitArgs); } // 探測是否有不確定性的構造函數存在,例如不同構造函數的參數為父子關系 int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes)); // Choose this constructor if it represents the closest match. // 如果它代表着當前最接近的匹配則選擇作為構造函數 if (typeDiffWeight < minTypeDiffWeight) { constructorToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; ambiguousConstructors = null; } else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) { if (ambiguousConstructors == null) { ambiguousConstructors = new LinkedHashSet<>(); ambiguousConstructors.add(constructorToUse); } ambiguousConstructors.add(candidate); } } if (constructorToUse == null) { if (causes != null) { UnsatisfiedDependencyException ex = causes.removeLast(); for (Exception cause : causes) { this.beanFactory.onSuppressedException(cause); } throw ex; } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Could not resolve matching constructor " + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)"); } else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Ambiguous constructor matches found in bean '" + beanName + "' " + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + ambiguousConstructors); } if (explicitArgs == null) { // 將解析的構造函數加入緩存 argsHolderToUse.storeCache(mbd, constructorToUse); } } try { final InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy(); Object beanInstance; if (System.getSecurityManager() != null) { final Constructor<?> ctorToUse = constructorToUse; final Object[] argumentsToUse = argsToUse; beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> strategy.instantiate(mbd, beanName, this.beanFactory, ctorToUse, argumentsToUse), this.beanFactory.getAccessControlContext()); } else { beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse); } // 將構建的實例加入BeanWrapper中 bw.setBeanInstance(beanInstance); return bw; } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean instantiation via constructor failed", ex); } }
邏輯很復雜,函數代碼量很大,不知道你是否堅持讀完了整個函數並理解了整個功能呢?這里要先葉個槽,筆者覺得這個函數的寫法完全不符合 Spring 的一貫風格,如果你一直跟隨筆者的分析思路到這里,相信你或多或少對 SPring 的編碼風格有所了解, Spring的一貫做法是將復雜的邏輯分解,分成 N 個小函數的嵌套,每一層都是對下一層邏輯的總結及概要,這樣使得每一層的邏輯會變得簡單容易理解。在上面的函數中,包含着很多的邏輯實現,筆者覺得至少應該將邏輯封裝在不同函數中而使得在 autowireConstructor 中的邏輯清晰明了。
我們總覽一下整個函數,其實現的功能考慮了以下幾個方面。
(1)構造函數參數的確定。
1)根據explicitArgs參數判斷。
如果傳人的參數explicitArgs不為空,那么可以直接確定參數,因為 explicitArgs參數是在調用 Bean 的時候用戶指定的,在 BeanFactory 類中存在這樣的方法:Object getBean(String name, Object... args) throws BeansException;
在獲取 bean 的時候,用戶不但可以指定 bean 的名稱還可以指定 bean 所對應類的構造函數或者工廠方法的方法參數,主要用於靜態工廠方法的調用,而這里是需要給定完全匹配的參數的,所以,便可以判斷,如果傳人參數 explicitArgs不為空,則可以確定構造函數參數就是它。
2)緩存中獲取。
除此之外,確定參數的辦法如果之前已經分析過,也就是說構造函數參數已經記錄在緩存中,那么便可以直接拿來使用。而且,這里要提到的是,在緩存中緩存的可能是參數的最終類型也可能是參數的初始類型,例如:構造函數參數要求的是 int 類型,但是原始的參數值可能是 String 類型的“1” ,那么即使在緩存中得到了參數,也需要經過類型轉換器的過濾以確保參數類型與對應的構造函數參數類型完全對應。
3)配置文件獲取。
如果不能根據傳人的參數 explicitArgs確定構造函數的參數也無法在緩存中得到相關信息,那么只能開始新一輪的分析了。
分析從獲取配置文件中配置的構造函數信息開始,經過之前的分析,我們知道, Spring配置文件中的信息經過轉換都會通過 BeanDefinition 實例承載,也就是參數 mbd 中包含,那么可以通過調用 mbd.getConstructorArgumentValues()來獲取配置的構造函數信息。有了配置中的信息便可以獲取對應的參數值信息了,獲取參數值的信息包括直接指定值,如:直接指定構造函數中某個值為原始類型 String 類型,或者是一個對其他 bean 的引用,而這一處理委托給 resolveConstruotorArgumcnts 方法,並返回能解析到的參數的個數。
( 2 )構造函數的確定。
經過了第一步后已經確定了構造函數的參數,接下來的任務就是根據構造函數參數在所有構造函數中鎖定對應的構造函數,而匹配的方法就是根據參數個數匹配,所以在匹配之前需要先對構造函數按照 public 構造函數優先參數數量降序、非 public 構造函數參數數量降序。這樣可以在遍歷的情況下迅速判斷排在后面的構造函數參數個數是否符合條件。
由於在配置文件中並不是唯一限制使用參數位置索引的方式去創建,同樣還支持指定參數名稱進行設定參數值的情況,如< constructor-arg name = "hello" > ,那么這種情況就需要首先確定構造函數中的參數名稱。
獲取參數名稱可以有兩種方式,一種是通過注解的方式直接獲取,另一種就是使用 Spring 中提供的工具類 ParameterNameDiscoverer來獲取。構造函數、參數名稱、參數類型、參數值都確定后就可以鎖定構造函數以及轉換對應的參數類型了。
(3)根據確定的構造函數轉換對應的參數類型。
主要是使用Spring 中提供的類型轉換器或者用戶提供的自定義類型轉換器進行轉換。
(4)構造函數不確定性的驗證。
當然,有時候即使構造函數、參數名稱、參數類型、參數值都確定后也不一定會直接鎖定構造函數,不同構造函數的參數為父子關系,所以 Spring 在最后又做了一次驗證。
(5)根據實例化策略以及得到的構造函數及構造函數參數實例化 Bean 。后面章節中將進行講解。
2 . instantiateBean
經歷了帶有參數的構造函數的實例構造,相信你會非常輕松愉快地理解不帶參數的構造函數的實例化過程。
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, parent), getAccessControlContext()); } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
你會發現,此方法並沒有什么實質性的邏輯,帶有參數的實例構造中,Spring 把精力都放在了構造函數以及參數的匹配上,所以如果沒有參數的話那將是非常簡單的一件事,直接調用實例化策略進行實例化就可以了。
3 . 實例化策略
實例化過程中反復提到過實例化策略,那這又是做什么用的呢?其實,經過前面的分析,我們已經得到了足以實例化的所有相關信息,完全可以使用最簡單的反射方法直接反射來構造實例對象,但是 Spring 卻並沒有這么做。
SimpleInstantiationStrategy.java
@Override public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. // 如果有需要覆蓋或者動態替換的方法則當然需要使用cglib進行動態代碼,因為可以在創建代理的同時將動態方法織入類中 // 但是如果沒有需要動態改變的方法,為了方便直接反射就可以了 if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class<?> clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor); } else { constructorToUse = clazz.getDeclaredConstructor(); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. return instantiateWithMethodInjection(bd, beanName, owner); } }
CglibSubclassingInstantiationStrategy.java
public Object instantiate(@Nullable Constructor<?> ctor, @Nullable Object... args) { Class<?> subclass = createEnhancedSubclass(this.beanDefinition); Object instance; if (ctor == null) { instance = BeanUtils.instantiateClass(subclass); } else { try { Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes()); instance = enhancedSubclassConstructor.newInstance(args); } catch (Exception ex) { throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex); } } // SPR-10785: set callbacks directly on the instance instead of in the // enhanced class (via the Enhancer) in order to avoid memory leaks. Factory factory = (Factory) instance; factory.setCallbacks(new Callback[] {NoOp.INSTANCE, new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner), new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)}); return instance; }
看了上面兩個函數后似乎我們已經感受到了 Spring 的良苦用心以及為了能更方便地使用 Spring 而做了大量的工作。程序中,首先判斷如果 bd.hasMethodOverrides為空也就是用戶沒有使用 replace 或者 lookup的配置方法,那么直接使用反射的方式,簡單快捷,但是如果使用了這兩個特性,在直接使用反射的方式創建實例就不妥了,因為需要將這兩個配置提供的功能切入進去,所以就必須要使用動態代理的方式將包含兩個特性所對應的邏輯的攔截增強器設置進去,這樣才可以保證在調用方法的時候會被相應的攔截器增強,返回值為包含攔截器的代理實例。
二、記錄創建bean的ObjectFactory
在doCreate函數中有這樣一段代碼:
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } // 為避免后期循環依賴,可以在bean初始化完成前將創建實例的ObjectFactory加入工廠 /** * getEarlyBeanReference(beanName, mbd, bean)方法: * 對bean再一次依賴引用,主要應用SmartInstantiationAwareBeanPostProcessor * 其中我們熟知的AOP就是在這里將advice動態織入bean中,若沒有則直接返回bean,不做任何處理 */ addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); }
這段代碼不是很復雜,但是很多人不是太理解這段代碼的作用,而且,這段代碼僅從此函數中去理解也很難弄懂其中的含義,我們需要從全局的角度去思考 Spring 的依賴解決辦法。
- earlySingletonExposure :從字面的意思理解就是提早曝光的單例,我們暫不定義它的學名叫什么,我們感興趣的是有哪些條件影響這個值。
- mbd.isSingleton() :沒有太多可以解釋的,此 RootBeanDefinition 代表的是否是單例。
- this.allowCircularReferences :是否允許循環依賴,很抱歉,並沒有找到在配置文件中如何配置,但是在 AbstractRefreshableApplicationContext 中提供了設置函數,可以通過硬編碼的方式進行設置或者可以通過自定義命名空間進行配置,其中硬編碼的方式代碼如下。
ClassPathXmlApplicationContext bf = ClassPathXmlApplicationContext("aspectTest.xml" ); bt.setAllowBeanDefinitionOverriding(false);
- isSingletonCurrentlylncreation(beanName) :該 bean 是否在創建中。在 Spring 中,會有個專門的屬性默認為 DefaultSingletonBeanRegistry的 singletonsCurrentlylnCreation 來記錄 bean 的加載狀態,在 bean 開始創建前會將 beanName 記錄在屬性中,在 bean 創建結束后會將 beanName 從屬性中移除。那么我們跟隨代碼一路走來可是對這個屬性的記錄並沒有多少印象,這個狀態是在哪里記錄的呢?不同 scope 的記錄位置並不一樣,我們以 singleton 為例,在 singleton 下記錄屬性的函數是在 DefaultSingletonBeanRegistry的 public Object getSingleton(String beanName, ObjectFactory singletonFactory)函數的 beforeSingletonCreation(beanName)和 afterSingletonCreation(beanName)中,在這兩段函數中分別this.singletonCurrentlylnCreation.add(beanName)與 this.singletonCurrentlylnCreation.remove(beanName)來進行狀態的記錄與移除。
經過以上分析我們了解變量 earl earlySingletonExposure 是否是單例、是否允許循環依賴、是否對應的 bean 正在創建的條件的綜合。當這 3 個條件都滿足時會執行 addSingletonFactory操作,那么加入 SingletonFactory的作用是什么呢?又是在什么時候調用呢?
我們還是以最簡單的AB循環依賴為例,類A中含有屬性類B,而類B中又會含有屬性類A,那么初始化beanA的過程如下圖所示:
上圖展示了創建 beanA 的流程,圖中我們看到,在創建 A 的時候首先會記錄類 A 所對應的 beanName,並將beanA的創建工廠加入緩存中,而在對 A的屬性填充也就是調用populate方法的時候又會再一次的對 B 進行遞歸創建。同樣的,因為在 B 中同樣存在 A 屬性,因此在實例化 B 的的 populate 方法中又會再次地初始化 A ,也就是圖形的最后,調用 getBean(A)。關鍵是在這里,有心的同學可以去找找這個代碼的實現方式,我們之前已經講過,在這個函數中並不是直接去實例化 A ,而是先去檢測緩存中是否有已經創建好的對應的 bean ,或者是否已經創建好的 ObjectFactory,而此時對於A的 ObjectFactory我們早已經創建,所以便不會再去向后執行,而是直接調用 ObjectFactory去創建 A 。這里最關鍵的是 ObjectFactory的實現。
/** * getEarlyBeanReference(beanName, mbd, bean)方法: * 對bean再一次依賴引用,主要應用SmartInstantiationAwareBeanPostProcessor * 其中我們熟知的AOP就是在這里將advice動態織入bean中,若沒有則直接返回bean,不做任何處理 */ addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
其中getEarlyBeanReference的代碼如下:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } } return exposedObject; }
在 getEarlyBeanReference 函數中並沒有太多的邏輯處理,或者說除了后處理器的調用外沒有別的處理工作,根據以上分析,基本可以理清 spring 處理循環依賴的解決辦法,在 B 中創建依賴 A 時通過 ObjectFactory 提供的實例化方法來中斷 A 中的屬性填充,使 B 中持有的 A 僅僅是剛剛初始化並沒有填充任何屬性的 A ,而這正初始化 A 的步驟還是在最開始創建 A 的時候進行的,但是因為 A 與 B 中的 A 所表示的屬性地址是一樣的,所以在 A 中創建好的屬性填充自然可以通過 B 中的 A 獲取,這樣就解決了循環依賴的問題。
三、屬性注入
在了解循環依賴的時候,我們曾經反復提到了 populateBean 這個函數,也多少了解了這個函數的主要功能就是屬性填充,那么究竟是如何實現填充的呢?
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. // 給InstantiationAwareBeanPostProcessors最后一次機會在屬性設置前來改變bean // 如:可以用來支持屬性注入的類型 boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 返回值為是否繼續填充bean if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } // 如果后處理器發出停止填充命令則終止后續的執行 if (!continueWithPropertyPopulation) { return; } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. // 根據名稱自動注入 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. // 根據類型自動注入 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } // 后處理器已經初始化 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // 需要依賴檢查 boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 對所有需要依賴檢查的屬性進行后處理 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { // 依賴檢查,對應depend-on屬性,3.0已經棄用此屬性 if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { // 將屬性應用到bean中 applyPropertyValues(beanName, mbd, bw, pvs); } }
在 populateBean 函數中提供了這樣的處理流程。
(1)InstantiationAwareBeanPostProcessor處理器的postProcessAfterInstantiation函數的應用,此函數可以控制程序是否繼續進行屬性填充。
(2)根據注入類型(byName/byType) ,提取依賴的 bean ,並統一存入 PropertyValues 中。
(3)應用InstantiationAwareBeanPostProcessor 處理器的postProcessPropertyValues方法,對屬性獲取完畢填充前對屬性的再次處理,典型應用是 RequiredAnnotationBeanPostProccssor 類中對屬性的驗證。
(4)將所有PropertyValues中的屬性填充至 BeanWrapper中。
在上面的步驟中有幾個地方是我們比較感興趣的,它們分別是依賴注人(autowireByName/autowireByType)以及屬性填充,那么,接下來進一步分析這幾個功能的實現細節。
1. autowireByName
上文提到根據注人類型(byName/byType) ,提取依賴的 bean ,並統一存入PropertyValues中,那么我們首先了解下 byName 功能是如何實現的。
protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { // 尋找bw中需要依賴注入的屬性 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { // 遞歸初始化相關的bean Object bean = getBean(propertyName); pvs.add(propertyName, bean); // 注冊依賴 registerDependentBean(propertyName, beanName); if (logger.isDebugEnabled()) { logger.debug("Added autowiring by name from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + propertyName + "'"); } } else { if (logger.isTraceEnabled()) { logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName + "' by name: no matching bean found"); } } } }
如果讀者之前了解過autowire的使用方法,相信理解這個函數的功能不會太困難,無非是在傳入參數pvs中找出已經加載的bean,並遞歸實例化,進而加入到pvs中。
2. autowireByType
autowireByName與autowireByType對於我們理解與使用來說復雜程度都很相似,但是其實現功能的復雜度卻完全不一樣。
protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<>(4); // 尋找bw中需要依賴注入的屬性 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { try { PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName); // Don't try autowiring by type for type Object: never makes sense, // even if it technically is a unsatisfied, non-simple property. if (Object.class != pd.getPropertyType()) { // 探測指定屬性的set方法 MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); // Do not allow eager init for type matching in case of a prioritized post-processor. boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance()); DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); // 解析指定beanName的屬性所匹配的值,並把解析到的屬性名稱存儲在autowiredBeanNames中,如: // @Autowired private List<A> list; 將會找到所有匹配A類型的bean並將其注入 Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); if (autowiredArgument != null) { pvs.add(propertyName, autowiredArgument); } for (String autowiredBeanName : autowiredBeanNames) { // 注冊依賴 registerDependentBean(autowiredBeanName, beanName); if (logger.isDebugEnabled()) { logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + autowiredBeanName + "'"); } } autowiredBeanNames.clear(); } } catch (BeansException ex) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex); } } }
實現根據名稱自動匹配的第一步就是尋找 bw 中需要依賴注入的屬性,同樣對於根據類型自動匹配的實現來講第一步也是尋找 bw 中需要依賴注入的屬性,然后遍歷這些屬性並尋找類型匹配的 bean ,其中最復雜的就是尋找類型匹配的 bean。同時,Spri ng 中提供了對集合的類型注人的支持,如使川注解的方式:
@Autowired private List<Test> tests;
Spring 將會把所有與 Test 匹配的類型找出來並注人到 tests 屬性中,正是由於這一因素,所以在 autowireByType 函數中,新建了局部遍歷 autowiredBeanNames,用於存儲所有依賴的 bean ,如果只是對非集合類的屬性注人來說,此屬性並無用處。
對於尋找類型匹配的邏輯實現封裝在了 resolveDependency 函數中。
@Override @Nullable public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); if (Optional.class == descriptor.getDependencyType()) { return createOptionalDependency(descriptor, requestingBeanName); } else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { // ObjectFactory類注入的特殊處理 return new DependencyObjectProvider(descriptor, requestingBeanName); } else if (javaxInjectProviderClass == descriptor.getDependencyType()) { // javaxInjectProviderClass類注入的特殊處理 return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName); } else { Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); if (result == null) { // 通用處理邏輯 result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } } @Nullable public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } Class<?> type = descriptor.getDependencyType(); // 用於支持Spring中新增的注解@Value Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } // 根據屬性類型找到beanFactory中所有類型的匹配bean, // 返回值的構成為:key=匹配的beanName, value=beanName對應的實例化后的bean(通過getBean(beanName)返回) Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { // 如果autowire的require屬性為true而找到的匹配項卻為空則只能拋出異常 if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; if (matchingBeans.size() > 1) { autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans); } else { // In case of an optional Collection/Map, silently ignore a non-unique case: // possibly it was meant to be an empty collection of multiple regular beans // (before 4.3 in particular when we didn't even look for collection beans). return null; } } instanceCandidate = matchingBeans.get(autowiredBeanName); } else { // We have exactly one match. // 已經可以確定只有一個匹配項 Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); } if (autowiredBeanNames != null) { autowiredBeanNames.add(autowiredBeanName); } if (instanceCandidate instanceof Class) { instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); } Object result = instanceCandidate; if (result instanceof NullBean) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } result = null; } if (!ClassUtils.isAssignableValue(type, result)) { throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass()); } return result; } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }
尋找類型的匹配執行順序時,首先嘗試使用解析器進行解析,如果解析器沒有成功解析,那么可能是使用默認的解析器沒有做任何處理,或者是使用了自定義的解析器,但是對於集合等類型來說並不在解析范圍之內,所以再次對不同類型進行不同情況的處理,雖說對於不同類型處理方式不一致,但是大致的思路還是很相似的,所以函數中只對數組類型進行了詳細地注釋。
3. applyPropertyValues
程序運行到這里,已經完成了對所有注人屬性的獲取,但是獲取的屬性是以 PropertyValues形式存在的,還並沒有應用到已經實例化的 bean 中,這一工作是在applyPropertyValues中。
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { if (pvs.isEmpty()) { return; } if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) { ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); } MutablePropertyValues mpvs = null; List<PropertyValue> original; if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; // 如果mpvs中的值已經被轉換為對應的類型,那么可以直接設置到beanWrapper中 if (mpvs.isConverted()) { // Shortcut: use the pre-converted values as-is. try { bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } original = mpvs.getPropertyValueList(); } else { // 如果pvs並不是使用MutablePropertyValues封裝的類型,那么直接使用原始的屬性獲取方法 original = Arrays.asList(pvs.getPropertyValues()); } TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } // 獲取對應的解析器 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // Create a deep copy, resolving any references for values. List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; // 遍歷屬性,將屬性轉換為對應類的對應屬性的類型 for (PropertyValue pv : original) { if (pv.isConverted()) { deepCopy.add(pv); } else { String propertyName = pv.getName(); Object originalValue = pv.getValue(); Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // Possibly store converted value in merged bean definition, // in order to avoid re-conversion for every created bean instance. if (resolvedValue == originalValue) { if (convertible) { pv.setConvertedValue(convertedValue); } deepCopy.add(pv); } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { pv.setConvertedValue(convertedValue); deepCopy.add(pv); } else { resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // Set our (possibly massaged) deep copy. try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
四、初始化bean
大家應該記得在 bean 配置時 bean 中有一個 init-method 的屬性,這個屬性的作用是在 bean 實例化前調用 init-method 指定的方法來根據用戶業務進行相應的實例化。我們現在就已經進入這個方法了,首先看一下這個方法的執行位置, Spring 中程序已經執行過 bean 的實例化,並且進行了屬性的填充,而就在這時將會調用用戶設定的初始化方法。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // 對特殊bean處理:Aware、BeanClassLoaderAware、BeanFactoryAware invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 應用后處理器 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 激活用戶自定義的init方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // 后處理器應用 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
雖然說此函數的主要日的是進行客戶設定的初始化方法的調用,但是除此之外還有些其他必要的工作。
1. 激活 Aware 方法
在分析其原理之前,我們先了解一下 Aware 的使用。 Spring 中提供一些 Aware 相關接口,比如BeanFactoryAware、 ApplicationContextWware 、ResourceLoaderAware 、ServletContextWware 等,實現這些Aware 接口的 bean 在被初始之后,可以取得一些相對應的資源,例如實現BeanFactoryAware的bean在初始后, Spring 容器將會注入BeanFactory的實例,而實現ApplicationContextWware的 bean,在 bean 被初始后,將會被注入 ApplicationContext 的實例等。我們首先通過示例方法來了解一下 Aware 的使用。
(1)定義普通 bean 。
public class Hello { public void say() { System.out.println("hello"); } }
(2)定義BeanFactoryAware類型的bean。
public class HelloBeanFactory implements BeanFactoryAware { private BeanFactory beanFactory; // 聲明bean的時候Spring會自動注入BeanFactory @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } public void testAware() { // 通過hello這個bean id從beanFactory獲取實例 Hello hello = (Hello) beanFactory.getBean("hello"); hello.say(); } }
(3)使用main方法測試。
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloBeanFactory factory = (HelloBeanFactory) context.getBean("factory"); factory.testAware(); }
測試類運行,控制台輸出:
hello
按照上面的方法我們可以獲取到Spring中BeanFactory,並且可以根據 BeanFactory獲取所有 bean,以及進行相關設置。當然還有其他 Aware 的使用方法都大同小異,看一下Spring 的實現方式,相信讀者便會使用了。
private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
代碼簡單得已經沒有什么好說的了。讀者可以自己嘗試使用別的 Aware,都比較簡單。
2 . 處理器的應用
BeanPostProcessor 相信大家都不陌生,這是 Spring 中開放式架構中一個必不可少的亮點,給用戶充足的權限去更改或者擴展 Spring ,而除了 BeanPostProcessor 外還有很多其他的 PostProcessor,當然大部分都是以此為基礎,繼承自BeanPostProcessor。 BeanPostProcessor的使用位置就是這里,在調用客戶自定義初始化方法前以及調用自定義初始化方法后分別會調用 BeanPostProcessor 的 postProcessBeforelnitialization 和postProcessAfterlnitialization 方法,使用戶可以根據自己的業務需求進行相應的處理。
@Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; } @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
3. 激活自定義的 init 方法
客戶定制的初始化方法除了我們熟知的使用配置 init-method 外,還有使自定義的 bean 實現InitializingBean接口,並在afterPropertiesSet中實現自己的初始化業務邏輯。
init-method 與afterPropertiesSet都是在初始化 bean 時執行,執行順序是 afterPropertiesSet先執行,而 init-method 后執行。
在invokeInitMethods方法中就實現了這兩個步驟的初始化方法調用。
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { // 首先會檢查是否是InitializingBean,如果是,需要調用afterPropertiesSet方法 boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((InitializingBean) bean).afterPropertiesSet(); return null; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { // 屬性初始化后的處理 ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null && bean.getClass() != NullBean.class) { String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { // 調用自定義初始化方法 invokeCustomInitMethod(beanName, bean, mbd); } } }
五、注冊 DisposableBean
Spring 中不但提供了對於初始化方法的擴展入口,同樣也提供了銷毀方法的擴展入口,對於銷毀方法的擴展,除了我們熟知的配置屬性 destroy-method 方法外,用戶還叮以注冊后處理器DestructionAwareBeanPostProcessor來統一處理 bean 的銷毀方法,代碼如下:
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null); if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { if (mbd.isSingleton()) { // Register a DisposableBean implementation that performs all destruction // work for the given bean: DestructionAwareBeanPostProcessors, // DisposableBean interface, custom destroy method. // 單例模式下注冊需要銷毀的bean,此方法中會處理實現DisposableBean的bean, // 並且對所有bean使用DestructionAwareBeanPostProcessor處理 registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); } else { // A bean with a custom scope... // 自定義scope的處理 Scope scope = this.scopes.get(mbd.getScope()); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'"); } scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); } } }