上文從整體視角分析了bean創建的流程,分析了Spring在bean創建之前所做的一些准備工作,並且簡單分析了一下bean創建的過程,接下來就要詳細分析bean創建的各個流程了,這是一個比較復雜的過程,也是Spring獲取bean中最核心的一部分,主要包括如下部分,下面依次進行詳細分析:
- 構造bean;
- 屬性注入;
- 初始化bean;
- 注冊DisposableBean;
1. 構造bean
構造bean的邏輯在createBeanInstance()方法中:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { // 解析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()); } // 如果工廠方法不為空則使用工廠方法初始化策略 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); } } // 需要根據參數解析構造函數 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { // 構造函數自動注入 return autowireConstructor(beanName, mbd, ctors, args); } // 使用默認構造函數構造 return instantiateBean(beanName, mbd); }
這里面的邏輯還是比較清晰的:
-
如果在RootBeanDefinition中存在factoryMethodName屬性,或者說在配置文件中配置了factory-method,那么Spring會嘗試使用instantiateUsingFactoryMethod()方法根據RootBeanDefinition中的配置生成bean的實例。
-
解析構造函數並進行構造函數的實例化。因為一個bean對應的類中可能會有多個構造函數,而每個構造函數的參數不同,Spring會根據參數及類型去判斷最終會使用哪個構造函數進行實例化。但是,判斷的過程是一個比較消耗性能的步驟,所以采用了緩存機制,即如果已經解析過則不需要重復解析而是直接從RootBeanDefinition中的屬性resolvedConstructorOrFactoryMethod緩存的值去取,否則需要再次解析,並將解析的結果添加至RootBeanDefinition中的resolvedConstructorOrFactoryMethod中。
下面再來看一下實例的創建,對於實例的創建Spring中分成了兩種情況,一種是通用的實例化,另一種是帶有參數的實例化。
1.1 帶參數構造函數實例化
帶有參數的實例化過程相當復雜,因為存在着不確定性,所以在判斷對應參數上做了大量工作,這個工作是委托給ConstructorResolver這個類:
public BeanWrapper autowireConstructor( final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, 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) { // 從緩存獲取 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); } } // 沒有被緩存 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,"some exception message ^_^", ex); } } // 排序給定的構造函數,public構造函數優先參數數量降序、非public構造函數參數數量降序 AutowireUtils.sortConstructors(candidates); int minTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<?>> ambiguousConstructors = null; List<Exception> causes = null; for (int i = 0; i < candidates.length; i++) { Constructor<?> candidate = candidates[i]; Class<?>[] paramTypes = candidate.getParameterTypes(); if (constructorToUse != null && argsToUse.length > paramTypes.length) { // 如果已經找到選用的構造函數並且需要的參數個數大於當前的構造函數參數個數則終止,因為已經按照參數個數降序排列 break; } if (paramTypes.length < minNrOfArgs) { // 參數個數不相等 continue; } ArgumentsHolder argsHolder; if (resolvedValues != null) { // 有參數則根據值構造對應參數類型的參數 try { String[] paramNames = null; if (constructorPropertiesAnnotationAvailable) { // 注解上獲取參數名稱 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, candidate, autowiring); } catch (UnsatisfiedDependencyException ex) { if (this.beanFactory.logger.isTraceEnabled()) { this.beanFactory.logger.trace( "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex); } if (i == candidates.length - 1 && constructorToUse == null) { if (causes != null) { for (Exception cause : causes) { this.beanFactory.onSuppressedException(cause); } } throw ex; } else { // Swallow and try next constructor. if (causes == null) { causes = new LinkedList<Exception>(); } 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)); // 如果它代表着當前最接近的匹配則選擇作為構造函數 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<Constructor<?>>(); ambiguousConstructors.add(constructorToUse); } ambiguousConstructors.add(candidate); } } if (constructorToUse == null) { throw new BeanCreationException(mbd.getResourceDescription(), beanName,"some exception message ^_^"); } else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName,"some exception message ^_^" + ambiguousConstructors); } if (explicitArgs == null) { // 將解析的構造函數加入緩存 argsHolderToUse.storeCache(mbd, constructorToUse); } } try { Object beanInstance; if (System.getSecurityManager() != null) { final Constructor<?> ctorToUse = constructorToUse; final Object[] argumentsToUse = argsToUse; beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { return beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, beanFactory, ctorToUse, argumentsToUse); } }, beanFactory.getAccessControlContext()); } else { beanInstance = this.beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, this.beanFactory, constructorToUse, argsToUse); } // 將構建的實例加入BeanWrapper中 bw.setWrappedInstance(beanInstance); return bw; } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
邏輯很復雜,代碼量也很大,能夠堅持讀完都不容易。總結一下整個函數,主要在以下幾個方面:
1. 構造函數參數的確定
- 根據explicitArgs參數判斷
如果傳入的參數explicitArgs不為空,那么可以直接確定參數,因為explicitArgs參數是在調用Bean的時候用戶指定的,在BeanFactory類中存在這樣的方法:
Object getBean(String name, Object... args) throws BeansException;
在獲取bean的時候,用戶不但可以指定bean的名稱還可以指定bean所對應類的構造函數或者工廠方法的方法參數,主要用於靜態工廠方法的調用,而這里是需要給定完全匹配的參數的,所以,便可以判斷,如果傳入參數explicitArgs不為空,則可以確定構造函數參數就是它。
- 從緩存中獲取
除此之外,確定參數的辦法如果之前已經分析過,也就是說構造函數參數已經記錄在緩存中,那么便可以直接拿來使用。而且,這里要提到的是,在緩存中緩存的可能是參數的最終類型也可能是參數的初始類型,例如:構造函數參數要求的是int類型,但是原始的參數值可能是String類型的"1",那么即使在緩存中得到了參數,也需要經過類型轉換器的過濾以確保參數類型與對應的構造函數參數類型完全對應。
- 從配置文件獲取
如果不能根據傳入的參數explicitArgs確定構造函數參數,也無法在緩存中得到相關信息,那么就只能從頭分析了。
經過之前的分析,我們知道,Spring中配置文件的信息經過轉換之后都會通過BeanDefinition實例承載,也就是參數mbd中包含的,那么可以通過調用mbd.getConstructorArgumentValues()來獲取配置的構造函數信息。有了配置中的信息便可以獲取對應的參數值信息了,獲取參數值的信息包括直接指定值,如:直接指定構造函數中某個值為原始類型或String類型,或者是一個對其他bean的引用,這一處理是委托給resolveConstructorArguments()方法,它將返回能解析到的參數的個數。
2. 構造函數的確定
經過了第一步后已經確定了構造函數的參數,接下來的任務就是根據構造函數參數在所有構造函數中鎖定對應的構造函數,而匹配的方法就是根據參數個數匹配,所以在匹配之前需要先對構造函數按照public構造函數優先參數數量降序、非public構造函數參數數量降序。這樣可以在遍歷的情況下迅速判斷排在后面的構造函數參數個數是否符合條件。
由於在配置文件中並不是唯一限制使用參數位置索引的方式去創建,同樣還支持指定參數名稱進行設定參數值的情況,如<constructor-arg name="aa">,那么這種情況就需要首先確定構造函數中的參數名稱。
獲取參數名稱有兩種方式,一種是通過注解的方式直接獲取,另一種就是使用Spring中提供的工具類ParameterNameDiscoverer來獲取。構造函數、參數名稱、參數類型、參數值都確定后就可以鎖定構造函數以及轉換對應的參數類型了。
3. 根據確定的構造函數轉換對應的參數類型
主要是使用Spring中提供的類型轉換器或者用戶提供的自定義類型轉換器進行轉換。
4. 構造函數不確定性的驗證
當然,有時候即使構造函數、參數名稱、參數類型、參數值都確定后也不一定會直接鎖定構造函數,不同構造函數的參數為父子關系,所以Spring在最后又做了一次驗證。
5. 根據實例化策略以及得到的構造函數及構造函數參數實例化Bean
1.2 不帶參數的構造函數實例化
相較於帶有參數的構造函數的實例構造,不帶參數的構造函數的實例化過程是很簡單的,就是直接調用實例化策略進行實例化,這里就不貼代碼了。
1.3 實例化策略
現在構造函數以及確定好了,具備了實例化的條件,完全可以使用最簡單的反射方法直接構造實例對象,但是Spring並沒有這么做:
// SimpleInstantiationStrategy.java public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) { // 如果有需要覆蓋或者動態替換的方法則當然需要使用cglib進行動態代理,因為可以在創建代理的同時將動態方法織入類中 // 但是如果沒有需要動態改變的方法,為了方便直接反射就可以了 if (beanDefinition.getMethodOverrides().isEmpty()) { Constructor<?> constructorToUse; synchronized (beanDefinition.constructorArgumentLock) { constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class<?> clazz = beanDefinition.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() { public Constructor<?> run() throws Exception { return clazz.getDeclaredConstructor((Class[]) null); } }); } else { constructorToUse = clazz.getDeclaredConstructor((Class[]) null); } beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Exception ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. return instantiateWithMethodInjection(beanDefinition, beanName, owner); } } // CglibSubclassingInstantiationStrategy.java public Object instantiate(Constructor<?> ctor, Object[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.beanDefinition.getBeanClass()); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setCallbackFilter(new CallbackFilterImpl()); enhancer.setCallbacks(new Callback[] { NoOp.INSTANCE, new LookupOverrideMethodInterceptor(), new ReplaceOverrideMethodInterceptor() }); return (ctor != null ? enhancer.create(ctor.getParameterTypes(), args) : enhancer.create()); }
上面的程序中,首先判斷如果beanDefinition.getMethodOverrides()為空也就是用戶沒有使用replace或者lookup的配置方法,那么直接使用反射的方式,簡單快捷,但是如果使用了這兩個特性,再直接使用反射的方式創建實例就不妥了,因為需要將這兩個配置提供的功能切入進去,所以就必須要使用動態代理的方式將包含兩個特性所對應的邏輯的攔截增強器設置進去,這樣才可以保證在調用方法的時候會被相應的攔截器增強,返回值為包含攔截器的代理實例。
2. 屬性注入
當創建好了bean的實例之后,接着就需要將bean中的屬性進行注入,這部分邏輯是在populateBean()方法中的,具體是如何實現的呢?
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // 沒有可填充的屬性 return; } } // 給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; } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 根據名稱自動注入 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 根據類型自動注入 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); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 對所有需要依賴檢查的屬性進行后處理 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { // 依賴檢查,對於depends-on屬性 checkDependencies(beanName, mbd, filteredPds, pvs); } } // 將屬性應用到bean中 applyPropertyValues(beanName, mbd, bw, pvs); }
在populateBean函數中提供了這樣的處理流程
- InstantiationAwareBeanPostProcessor處理器的postProcessorAfterInstantiation函數的應用,此函數可以控制程序是否繼續進行屬性填充;
- 根據注入類型(byName/byType),提取依賴的bean,並統一存入PropertyValues中;
- 應用InstantiationAwareBeanPostProcessor處理器的postProcessorPropertyValues()方法,在屬性獲取完畢並在填充前對屬性進行再次處理,典型應用是RequiredAnnotationBeanPostProcessor類中對屬性的驗證;
- 將所有PropertyValues中的屬性填充至BeanWrapper中;
在上面的步驟中,我們着重分析一下依賴注入(autoworeByName/autowireByType)以及屬性填充。
2.1 autowireByName
首先來了解一下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"); } } } }
這里無非是在傳入的參數pvs中找出已經加載的bean,並遞歸實例化,進而加入到pvs中。
2.2 autowireByType
autowireByType與autowireByName在使用和理解層面上復雜程度相似,但是其實現的復雜程度卻完全不一樣。
protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<String>(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.equals(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.isAssignableFrom(bw.getWrappedClass()); DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); // 解析指定beanName的屬性所匹配的值,並把解析到的屬性名稱存儲在autowiredBeanName中,當屬性存在多個封裝bean時,如: // @Autowired private List<A> aList;將會找到所有匹配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。Spring也提供了對集合的類型注入的支持,如使用注解的方式:
@Autowired private List<Test> tests;
Spring將會把所有與Test匹配的類型找出來並注入到tests屬性中,正是由於這一因素,所以在autowireByType函數中,新建了局部變量autowiredBeanNames,用於存儲所有依賴的bean,如果只是對非集合類的屬性注入來說,此屬性並無用處。
對於尋找類型匹配的邏輯實現封裝在了resolveDependency()函數中:
public Object resolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); if (descriptor.getDependencyType().equals(ObjectFactory.class)) { // ObjectFactory類注入的特殊處理 return new DependencyObjectFactory(descriptor, beanName); } else if (descriptor.getDependencyType().equals(javaxInjectProviderClass)) { // javaxInjectProviderClass類注入的特殊處理 return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName); } else { // 通用處理邏輯 return doResolveDependency(descriptor, descriptor.getDependencyType(), beanName, autowiredBeanNames, typeConverter); } } protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { // 用於支持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())); } // 如果解析器沒有成功解析,則需要考慮各種情況 // 屬性時數組類型 if (type.isArray()) { Class<?> componentType = type.getComponentType(); // 根據屬性類型找到beanFactory中所有類型的匹配bean, // 返回值的構成為:key=匹配的beanName,value=beanName 對應的實例化后的bean(通過getBean(beanName)返回) Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor); if (matchingBeans.isEmpty()) { // 如果autowire的require屬性為true而找到的匹配項卻為空則只能拋出異常 if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor); } return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); // 通過轉換器將bean的值轉換為對應的type類型 return converter.convertIfNecessary(matchingBeans.values(), type); } // 屬性是Collection類型 else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { Class<?> elementType = descriptor.getCollectionType(); if (elementType == null) { if (descriptor.isRequired()) { throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]"); } return null; } Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor); } return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); return converter.convertIfNecessary(matchingBeans.values(), type); } // 屬性是Map類型 else if (Map.class.isAssignableFrom(type) && type.isInterface()) { Class<?> keyType = descriptor.getMapKeyType(); if (keyType == null || !String.class.isAssignableFrom(keyType)) { if (descriptor.isRequired()) { throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() + "] must be assignable to [java.lang.String]"); } return null; } Class<?> valueType = descriptor.getMapValueType(); if (valueType == null) { if (descriptor.isRequired()) { throw new FatalBeanException("No value type declared for map [" + type.getName() + "]"); } return null; } Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor); } return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } return matchingBeans; } else { Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(type, "", descriptor); } return null; } if (matchingBeans.size() > 1) { String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor); if (primaryBeanName == null) { throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet()); } if (autowiredBeanNames != null) { autowiredBeanNames.add(primaryBeanName); } return matchingBeans.get(primaryBeanName); } // 已經可以確定只有一個匹配項 Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); if (autowiredBeanNames != null) { autowiredBeanNames.add(entry.getKey()); } return entry.getValue(); } }
這里首先嘗試使用解析器進行解析,如果解析器沒有成功解析,那么可能是使用默認的解析器沒有做任何處理,或者是使用了自定義的解析器,但是對於集合等類型來說並不在解析范圍之內,所以會再次對不同集合類型進行不同情況的處理,雖然對於不同集合類型處理方式不一致,但是大致思路是很相似的,所以這里只分析一下對數組類型的解析:
- 首先獲取數組封裝的類型;
- 根據屬性類型找到beanFactory中所有類型的匹配bean;
- 將找到的所有匹配的beanName加入到傳入的autowiredBeanNames中;
- 對找到的所有匹配的bean轉換為對應的type類型並返回;
2.3 applyPropertyValues
到這里,已經完成了對所有注入屬性的獲取,但是獲取的屬性是以PropertyValues形式存在的,還沒有應用到已經實例化的bean中,這一工作是在applyPropertyValues中:
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { if (pvs == null || pvs.isEmpty()) { return; } MutablePropertyValues mpvs = null; List<PropertyValue> original; if (System.getSecurityManager() != null) { if (bw instanceof BeanWrapperImpl) { ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); } } if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; // 如果mpvs中的值已經被轉換為對應的類型那么可以直接設置到beanwapper中 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<PropertyValue>(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); } }
3. 初始bean
在bean配置時bean中有一個init-method的屬性,這個屬性的作用是在bean初始化時調用init-method屬性指定的方法來根據用戶業務執行相應的初始化工作,初始化的工作是在bean完成實例化並且進行了屬性填充之后進行的。實現這個功能的代碼在initializeBean()方法中:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { 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; }
這里除了調用用戶指定的方法執行初始化,還做了其它一些操作,主要有激活Aware方法、應用后處理器、激活自定義的init方法。
3.1 激活Aware方法
我們先了解一下Aware的使用,Spring中提供了一些Aware相關接口,比如BeanFactoryAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware等,實現這些Aware接口的bean在被初始化之后,可以取得一些相對應的資源,例如實現了BeanFactoryAware接口的bean在初始化后,Spring容器將會注入BeanFactory的實例,而實現了ApplicationContextAware接口的bean,在bean被初始化后,將會被注入ApplicationContext的實例等。這里先通過示例方法來了解一下Aware的使用:
// 定義普通bean public class Hello { public void say(){ System.out.println("hello"); } } // 定義BeanFactoryAware類型的bean public class Test 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(); } } // 使用main方法測試 public static void main(String[] args){ ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Test test = (Test)ctx.getBean("test"); test.testAware(); }
運行測試類,控制台會輸出:hello
按照上面的方法我們可以獲取到Spring中BeanFactory,並且可以根據BeanFactory獲取所有bean,以及進行相關設置。當然還有其他Aware的使用方法都大同小異,這里就不一一列舉了。我們接下來看一下Spring是如何激活Aware方法的。
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) { ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
這個就是直接判斷是否實現接口,然后調用對應的set方法。
3.2 處理器的應用
BeanPostProcessor相信用過Spring的同學都聽過,這是Spring中開放式架構中一個必不可少的亮點,給用戶充足的權限去更改或者擴展Spring,而除了BeanPostProcessor外還有很多其他的PostProcessor,都是繼承自BeanPostProcessor,給用戶提供接口進行擴展,這又是如何實現的呢?其實就是在調用用戶自定義的init方法之前和之后分別調用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法,用戶可以在這兩個方法中定義自己的業務邏輯。
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; } public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName); if (result == null) { return result; } } return result; }
3.3 激活自定義的init方法
由用戶定制的初始化方法除了我們熟知的使用配置init-method外,還有讓自定義的bean實現InitializingBean接口,並在afterPropertiesSet中實現自己的初始化業務邏輯。
init-method與afterPropertiesSet都是在初始化bean時執行,執行順序是afterPropertiesSet先執行,而init-method后執行。
在invokeInitMethod()方法中就實現了這兩個步驟的初始化方法調用:
protected void invokeInitMethods(String beanName, final Object bean, 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(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { ((InitializingBean) bean).afterPropertiesSet(); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { // 屬性初始化后的處理 ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { // 調用自定義初始化方法 invokeCustomInitMethod(beanName, bean, mbd); } } }
4. 注冊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()) { // 單例模式下注冊需要銷毀的bean,此方法中會處理實現DisposableBean的bean, // 並且所有的bean使用DestructionAwareBeanPostProcessors處理 // DisposableBean DestructionAwareBeanPostProcessors registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); } else { // 自定義scope的處理 Scope scope = this.scopes.get(mbd.getScope()); if (scope == null) { throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'"); } scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); } } }
5. 總結
本文篇幅稍長,詳細分析了創建bean的各個步驟,包括構造bean、屬性注入、初始化bean、注冊DisposableBean,其中構造bean和屬性注入的邏輯比較復雜,初始化和注冊DisposableBean相對簡單。
構造bean大致流程如下(帶參數構造函數):
- 構造函數參數的確定
- 構造函數的確定
- 構造函數的確定
- 根據實例化策略以及得到的構造函數及構造函數參數實例化Bean
屬性注入大致流程如下:
- 尋找需要依賴注入的屬性
- 根據名稱/類型尋找匹配的屬性bean
- 注入屬性
歷經艱難,至此bean的加載就完成了,到這里應該也能夠感受到一個簡單IOC思想在Spring那里實現起來有多復雜了!能看到這里的同學都不容易,為自己點個贊吧!