Spring Bean的實例化之屬性註入源碼剖析過程
前言
這一章節我們來討論創建Bean過程中的屬性註入,在Spring的IOC容器啟動過程中,會把定義的Bean封裝成BeanDefinition註冊到一個ConcurrentHashMap中,Bean註冊完成後,就會對單利的且lazy-init=false 的Bean進行實例化。創建Bean的代碼在 AbstractAutowireCapableBeanFactory#doCreateBean 中,當Bean創建成功之後,會調用AbstractAutowireCapableBeanFactory#populateBean 方法進行屬性註入。本篇文章主要就是分析該方法是如何實現Bean的屬性註入的。
這裡先上一個屬性註入的流程圖,待會兒可以根據這個圖來看代碼
屬性註入:AbstractAutowireCapableBeanFactory#populateBean
AbstractAutowireCapableBeanFactory#populateBean 方法的主要功能就是屬性填充,源碼如下
//使用 bean 定義中的屬性值填充給定 BeanWrapper 中的 bean 實例。 @SuppressWarnings("deprecation") // for postProcessPropertyValues protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { //判斷是否有property屬性 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的狀態 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } //從 RootBeanDefinition 獲取所有的PropertyValues PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); int resolvedAutowireMode = mbd.getResolvedAutowireMode(); //根據名字獲取根據type註入 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; } //後置處理器是否已經註冊,初始化好瞭 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); //是否要檢查依賴,默認false boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } //獲取後置處理器 for (BeanPostProcessor bp : getBeanPostProcessors()) { //如果是Bean實例化後置處理器 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) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { //依賴註入入口,講屬性應用到Bean中 applyPropertyValues(beanName, mbd, bw, pvs); } }
方法中的重要代碼
- autowireByName : 根據屬性名進行註入
- autowireByType:根據類型註入Bean
- InstantiationAwareBeanPostProcessor.postProcessPropertyValues :該方法是在工廠將給定的屬性值應用於給定的 bean 之前對給定的屬性值進行處理,比如:RequiredAnnotationBeanPostProcessor類中對屬性的驗證。
- applyPropertyValues:屬性的填充
autowireByName是根據名字註入,源碼如下
protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { //尋找BeanWrapper中需要依賴的屬性 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { //遞歸實例化的Bean Object bean = getBean(propertyName); pvs.add(propertyName, bean); //註冊依賴的Bean,加入 dependentBeanMap 中 registerDependentBean(propertyName, beanName); if (logger.isTraceEnabled()) { logger.trace("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"); } } } }
這個方法很簡單,就是先找到依賴的Bean,遞歸初始化,然後加入 pvs中
//定義“按類型自動裝配”(按類型的 bean 屬性)行為的抽象方法 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); //找到需要註入的屬性 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 = !(bw.getWrappedInstance() instanceof PriorityOrdered); //依賴描述 DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); //【重要】得到依賴的屬性的值,存儲到 autowiredBeanNames 集合中 //提供瞭對集合如:@Autowired private List<A> as; 支持,根據類型走到所有的Bean註入其中 Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); if (autowiredArgument != null) { //添加到pvs pvs.add(propertyName, autowiredArgument); } for (String autowiredBeanName : autowiredBeanNames) { //註入依賴的Bean registerDependentBean(autowiredBeanName, beanName); if (logger.isTraceEnabled()) { logger.trace("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); } } }
看到這,我們大概清楚瞭,其實在populateBean 方法中會先從RootBeanDefinition 中獲取 Bean的屬性(PropertyValues),同時也會根據RootBeanDefinition的autowireMode自動註入模式來根據name或者type尋主Bean的依賴的屬性。
根據類型註入和根據名字註入都是先從BeanWrapper 中找到Bean的依賴的屬性,然後根據屬性類型找到匹配的Bean,實現依賴註入。還提供瞭對集合如:@Autowired private List<A> as;
集合註入的支持。
屬性尋找好之後都會封裝成 PropertyValues,然後傳給applyPropertyValues應用到Bean身上。
AbstractAutowireCapableBeanFactory#applyPropertyValues
我們可以認為前面的代碼是在為當前Bean尋找依賴的的屬性,封裝到 PropertyValues中,在applyPropertyValues中才是把屬性應用到當前Bean。
//處理對象之間的引用,使用深拷貝 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 { //如果類型不是MutablePropertyValues , 就使用原生屬性獲取方法 original = Arrays.asList(pvs.getPropertyValues()); } //獲取用戶自定義的型轉換器 TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } //解析器:用於 bean 工廠實現的 Helper 類,將 bean 定義對象中包含的值,解析為應用於目標 bean 實例的實際值。 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // Create a deep copy, resolving any references for values. //存放類型轉換過的屬性,把Bean的屬性解析值新建拷貝,把拷貝的數據註入到對象 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(); //原始屬性值,它的類型是一個 如: RuntimeBeanReference<otherBean> 引用類型 Object originalValue = pv.getValue(); //轉換屬性值,將引用轉換為 IOC 容器中實例化對象引用 OtherBean 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 ,把依賴的Bean設置給PropertyValue 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; //轉換好的依賴的屬性最終放到一個ArrayList中 deepCopy.add(new PropertyValue(pv, convertedValue)); } } } if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // Set our (possibly massaged) deep copy. try { //把解析好的屬性 設置到 BeanWrapper 中 bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
這裡主要進行屬性轉換,然後應用到Bean身上,這裡的屬性轉換比如: 在BeanDefinition中屬性可能是用字符串類型來描述的,需要把屬性轉成真實的原始屬性類型。
- 首先判斷屬性是否需要轉換類型,如果不需要轉直接應用於Bean。比如:
<property name="otherBean" ref="otherBean" />
這種屬性值其實是個字符串“otherBean” ,需要解析成容器中的OtherBean實例的引用。 - 如果屬性值需要類型轉換,比如:屬性值是容器中的另外一個Bean,則需要根據屬性值解析出引用的對象然後註入到對象的屬性上,應用到Bean。
通過 BeanDefinitionValueResolver 類中的 resolveValueIfNecessary()方法中進行屬性值的解析, 對屬性值的註入是通過 bw.setPropertyValues()方法完成
解析: BeanDefinitionValueResolver#resolveValueIfNecessary
給定一個 PropertyValue根據屬性值進行類型解析,必要時解析對工廠中其他 bean 的引用
@Nullable public Object resolveValueIfNecessary(Object argName, @Nullable Object value) { // We must check each value to see whether it requires a runtime reference // to another bean to be resolved. //對屬性值是引用類型的解析 if (value instanceof RuntimeBeanReference) { //比如:<property name="xx" ref="xxBean" 就是引用類型,會走這裡 RuntimeBeanReference ref = (RuntimeBeanReference) value; //對引用類型屬性進行解析 return resolveReference(argName, ref); } ///對屬性值是引用容器中另一個 Bean 名稱的解析 else if (value instanceof RuntimeBeanNameReference) { String refName = ((RuntimeBeanNameReference) value).getBeanName(); refName = String.valueOf(doEvaluate(refName)); //判斷容器中是否有這個Bean if (!this.beanFactory.containsBean(refName)) { throw new BeanDefinitionStoreException( "Invalid bean name '" + refName + "' in bean reference for " + argName); } return refName; } else if (value instanceof BeanDefinitionHolder) { // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases. //解析 BeanDefinitionHolder:包含帶有名稱和別名的 BeanDefinition BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value; //解析內部 Bean return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition()); } else if (value instanceof BeanDefinition) { // Resolve plain BeanDefinition, without contained name: use dummy name. //解析純 BeanDefinition,不包含名稱 BeanDefinition bd = (BeanDefinition) value; String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(bd); return resolveInnerBean(argName, innerBeanName, bd); } //對數組類型解析 else if (value instanceof ManagedArray) { // May need to resolve contained runtime references. ManagedArray array = (ManagedArray) value; Class<?> elementType = array.resolvedElementType; if (elementType == null) { String elementTypeName = array.getElementTypeName(); if (StringUtils.hasText(elementTypeName)) { try { elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader()); array.resolvedElementType = elementType; } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error resolving array type for " + argName, ex); } } else { elementType = Object.class; } } return resolveManagedArray(argName, (List<?>) value, elementType); } //對集合類型解析 else if (value instanceof ManagedList) { // May need to resolve contained runtime references. return resolveManagedList(argName, (List<?>) value); } //對Set類型解析 else if (value instanceof ManagedSet) { // May need to resolve contained runtime references. return resolveManagedSet(argName, (Set<?>) value); } //對Map類型解析 else if (value instanceof ManagedMap) { // May need to resolve contained runtime references. return resolveManagedMap(argName, (Map<?, ?>) value); } //對Properties解析 else if (value instanceof ManagedProperties) { Properties original = (Properties) value; Properties copy = new Properties(); original.forEach((propKey, propValue) -> { if (propKey instanceof TypedStringValue) { propKey = evaluate((TypedStringValue) propKey); } if (propValue instanceof TypedStringValue) { propValue = evaluate((TypedStringValue) propValue); } if (propKey == null || propValue == null) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error converting Properties key/value pair for " + argName + ": resolved to null"); } copy.put(propKey, propValue); }); return copy; } //解析字符串類型的屬性值 else if (value instanceof TypedStringValue) { // Convert value to target type here. TypedStringValue typedStringValue = (TypedStringValue) value; Object valueObject = evaluate(typedStringValue); try { //目標類型 Class<?> resolvedTargetType = resolveTargetType(typedStringValue); if (resolvedTargetType != null) { //目標類型進行解析 return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType); } else { //類型沒獲取到,就返回Object類型 return valueObject; } } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, ex); } } else if (value instanceof NullBean) { return null; } else { return evaluate(value); } }
這個方法中就是根據屬性的值的類型進行解析,如:String,Array,List,Set,Map的類型,比較復雜的就是屬性值依賴的是一個Bean,那麼就需要根據依賴的Bean的名字找到容器中的Bean的實例,查找如下:
/** * Resolve a reference to another bean in the factory. */ //關聯對象的解析 @Nullable private Object resolveReference(Object argName, RuntimeBeanReference ref) { try { Object bean; //引用對象的名稱 String refName = ref.getBeanName(); refName = String.valueOf(doEvaluate(refName)); //如果對象在父容器中,從父容器獲取 if (ref.isToParent()) { if (this.beanFactory.getParentBeanFactory() == null) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Can't resolve reference to bean '" + refName + "' in parent factory: no parent factory available"); } //如果對象在父容器中,從父容器獲取 bean = this.beanFactory.getParentBeanFactory().getBean(refName); } else { //[重要]根據依賴的Bean的名字,從當前容器中獲取Bean bean = this.beanFactory.getBean(refName); //把依賴的Bean的實例和當前對象建議依賴關系,使用 dependentBeanMap 去維護關系 this.beanFactory.registerDependentBean(refName, this.beanName); } if (bean instanceof NullBean) { bean = null; } return bean; } catch (BeansException ex) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex); } } * For each element in the managed array, resolve reference if necessary. */ //解析數組 private Object resolveManagedArray(Object argName, List<?> ml, Class<?> elementType) { Object resolved = Array.newInstance(elementType, ml.size()); for (int i = 0; i < ml.size(); i++) { Array.set(resolved, i, resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i))); } return resolved; } /** * For each element in the managed list, resolve reference if necessary. */ //解析List private List<?> resolveManagedList(Object argName, List<?> ml) { List<Object> resolved = new ArrayList<>(ml.size()); for (int i = 0; i < ml.size(); i++) { resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i))); } return resolved; } /** * For each element in the managed set, resolve reference if necessary. */ //解析set private Set<?> resolveManagedSet(Object argName, Set<?> ms) { Set<Object> resolved = new LinkedHashSet<>(ms.size()); int i = 0; for (Object m : ms) { resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m)); i++; } return resolved; } /** * For each element in the managed map, resolve reference if necessary. */ //解析Map private Map<?, ?> resolveManagedMap(Object argName, Map<?, ?> mm) { Map<Object, Object> resolved = new LinkedHashMap<>(mm.size()); mm.forEach((key, value) -> { Object resolvedKey = resolveValueIfNecessary(argName, key); Object resolvedValue = resolveValueIfNecessary(new KeyedArgName(argName, key), value); resolved.put(resolvedKey, resolvedValue); }); return resolved; }
屬性值解析完成之後 是封裝成一個 MutablePropertyValues,通過 BeanWrapperImpl.setPropertyValues()方法完成值的註入,BeanWrapperImpl中註入方法又是由AbstractPropertyAccessor#setPropertyValue(java.lang.String, java.lang.Object)去完成。
AbstractPropertyAccessor#setPropertyValue
@Override public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException { List<PropertyAccessException> propertyAccessExceptions = null; //拿到所有的屬性列表 List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ? ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues())); for (PropertyValue pv : propertyValues) { try { // This method may throw any BeansException, which won't be caught // here, if there is a critical failure such as no matching field. // We can attempt to deal only with less serious exceptions. //設置屬性值 setPropertyValue(pv); } ...省略... @Override public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException { //屬性訪問器 AbstractNestablePropertyAccessor nestedPa; try { nestedPa = getPropertyAccessorForPropertyPath(propertyName); } catch (NotReadablePropertyException ex) { throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, "Nested property in path '" + propertyName + "' does not exist", ex); } //屬性助手 PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName)); //通過屬性訪問器為屬性設置值 nestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value)); }
這裡看到,屬性的註入交給瞭 AbstractNestablePropertyAccessor 屬性訪問器去完成
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException { if (tokens.keys != null) { processKeyedProperty(tokens, pv); } else { //走這裡 processLocalProperty(tokens, pv); } } private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) { //屬性處理器 PropertyHandler ph = getLocalPropertyHandler(tokens.actualName); if (ph == null || !ph.isWritable()) { if (pv.isOptional()) { if (logger.isDebugEnabled()) { logger.debug("Ignoring optional value for property '" + tokens.actualName + "' - property not found on bean class [" + getRootClass().getName() + "]"); } return; } else { throw createNotWritablePropertyException(tokens.canonicalName); } } Object oldValue = null; try { //原生值 Object originalValue = pv.getValue(); Object valueToApply = originalValue; ...省略... //這是重點,通過 PropertyHandler 把屬性值設置給對象 ph.setValue(valueToApply); } catch (TypeMismatchException ex) { throw ex; }
這裡的屬性值通過 PropertyHandler去設置
@Override public void setValue(@Nullable Object value) throws Exception { //得到屬性的set方法 Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ? ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() : this.pd.getWriteMethod()); if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { ReflectionUtils.makeAccessible(writeMethod); return null; }); try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> writeMethod.invoke(getWrappedInstance(), value), acc); } catch (PrivilegedActionException ex) { throw ex.getException(); } } else { //設置訪問權限 ReflectionUtils.makeAccessible(writeMethod); //調用set方法把屬性值設置進去 writeMethod.invoke(getWrappedInstance(), value); } }
這裡就是得到屬性的set方法,然後調用set方法把值註入進去。
構造器註入參數
在之前分析Bean的創建的時候我們就說到,在 AbstractAutowireCapableBeanFactory#createBeanInstance 中會通過反射獲取到Bean的構造器,如果是有參構造就會走autowireConstructor 方法,通過有參構造創建實例
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. Class<?> beanClass = resolveBeanClass(mbd, beanName); ...省略... // 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); }
在autowireConstructor方法中會通過 ConstructorResolver 對構造器參數進行解析
protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) { //構造器解析器,註入 return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs); } public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) { ...省略... else { //得到構造器參數 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); //得到構造器參數值 resolvedValues = new ConstructorArgumentValues(); //解析參數值【重要】 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); } ...省略... try { //實例化策略 final InstantiationStrategy strategy = 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, beanFactory, ctorToUse, argumentsToUse), beanFactory.getAccessControlContext()); } else { //實例化對象,根據有參構造器,使用反射創建實例 beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse); } bw.setBeanInstance(beanInstance); return bw; }
resolveConstructorArguments 方法中又通過 BeanDefinitionValueResolver來解析屬性值,有參數的值瞭,就會走反射,根據有參構造器創建實例返回。
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) { TypeConverter customConverter = this.beanFactory.getCustomTypeConverter(); TypeConverter converter = (customConverter != null ? customConverter : bw); //屬性值的解析器 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); ...省略... for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) { if (valueHolder.isConverted()) { resolvedValues.addGenericArgumentValue(valueHolder); } else { //為構造器參數值做解析,這裡和之前分析的set註入的屬性值解析就一樣瞭 Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue()); ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder( resolvedValue, valueHolder.getType(), valueHolder.getName()); resolvedValueHolder.setSource(valueHolder); resolvedValues.addGenericArgumentValue(resolvedValueHolder); } } return minNrOfArgs; }
因為之前 resolveValueIfNecessary方法已經分析過瞭,這裡就不多說瞭。
總結
到這裡屬性註入的流程就分析完瞭,總結都在這個圖上
喜歡的話就給個好評吧,你的肯定是我堅持寫作最大的動力,來吧兄弟們,給我一點動力
以上就是Spring Bean的實例化之屬性註入源碼剖析過程的詳細內容,更多關於Spring Bean 實例化屬性註入的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Spring populateBean屬性賦值和自動註入
- 關於Spring Bean實例過程中使用反射和遞歸處理的Bean屬性填充問題
- 手把手帶你實現一個萌芽版的Spring容器
- 深入瞭解Spring的Bean生命周期
- Spring源碼解析之Bean的生命周期