久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術文章
文章詳情頁

Spring Bean的實例化之屬性注入源碼剖析過程

瀏覽:172日期:2023-07-10 15:40:46
前言

這一章節我們來討論創建Bean過程中的屬性注入,在Spring的IOC容器啟動過程中,會把定義的Bean封裝成BeanDefinition注冊到一個ConcurrentHashMap中,Bean注冊完成后,就會對單利的且lazy-init=false 的Bean進行實例化。創建Bean的代碼在 AbstractAutowireCapableBeanFactory#doCreateBean 中,當Bean創建成功之后,會調用AbstractAutowireCapableBeanFactory#populateBean 方法進行屬性注入。本篇文章主要就是分析該方法是如何實現Bean的屬性注入的。

這里先上一個屬性注入的流程圖,待會兒可以根據這個圖來看代碼

Spring Bean的實例化之屬性注入源碼剖析過程

屬性注入:AbstractAutowireCapableBeanFactory#populateBean

AbstractAutowireCapableBeanFactory#populateBean 方法的主要功能就是屬性填充,源碼如下

//使用 bean 定義中的屬性值填充給定 BeanWrapper 中的 bean 實例。@SuppressWarnings('deprecation') // for postProcessPropertyValuesprotected 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 獲取所有的PropertyValuesPropertyValues 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();//是否要檢查依賴,默認falseboolean 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)) {//遞歸實例化的BeanObject 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) {//添加到pvspvs.add(propertyName, autowiredArgument);}for (String autowiredBeanName : autowiredBeanNames) {//注入依賴的BeanregisterDependentBean(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 容器中實例化對象引用 OtherBeanObject 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設置給PropertyValuepv.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 的引用

@Nullablepublic 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));//判斷容器中是否有這個Beanif (!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:包含帶有名稱和別名的 BeanDefinitionBeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;//解析內部 Beanreturn 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. */ //關聯對象的解析@Nullableprivate 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的名字,從當前容器中獲取Beanbean = 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. */ //解析Listprivate 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. */ //解析setprivate 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. */ //解析Mapprivate 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

@Overridepublic 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);}...省略...@Overridepublic 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去設置

@Overridepublic 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的實例化之屬性注入源碼剖析過程的詳細內容,更多關于Spring Bean 實例化屬性注入的資料請關注好吧啦網其它相關文章!

標簽: Spring
相關文章:
主站蜘蛛池模板: 在线视频一区二区 | 亚洲免费视频网站 | 国产二区在线播放 | 精品久| 人成亚洲 | 国产精品伊人 | 视频一区二区三区中文字幕 | 免费看91 | 夜夜天天操 | 综合久久精品 | 精品亚洲一区二区 | 一区二区三区精品 | 午夜免费福利电影 | 国产精品国产精品国产专区不卡 | 久久国产精品系列 | 欧美色视 | 国际精品久久 | 久久三区 | 色呦呦日韩 | 日韩大片播放器 | 黑色丝袜脚足j国产在线看68 | 成人在线观看网 | va在线| 中文亚洲欧美 | 青青久久 | 伊人免费在线观看高清版 | 国产精品久久久久久妇女6080 | 一区二区日韩精品 | 91久久精品一区二区三区 | 狠狠操av | 国产福利一区二区三区视频 | 欧美一区二区三区黄色 | 91精品一区二区 | 国产精品一区在线观看你懂的 | 神马久久久久久久 | 玖玖免费 | 午夜在线观看免费 | 日韩视频在线观看一区二区 | 久久久激情视频 | 国产黄网 | 亚洲视频区 | 亚洲欧美一区二区三区在线 | 亚洲成人精品av | 亚洲精品99 | 久久成人精品一区二区三区 | 2024天天干| 久久精品一区二区三区四区 | 亚洲精品一二区 | 午夜看片| 岛国av一区| av观看免费 | 午夜激情av | 拍拍无遮挡人做人爱视频免费观看 | 精品国产91亚洲一区二区三区www | 国产日韩欧美一区二区 | 99视频免费在线观看 | 春色导航 | 黄色av网站免费 | 精品一区二区三区在线观看视频 | 一区二区在线不卡 | 国产日韩在线视频 | 日韩电影一区 | 亚洲高清视频在线 | 国产精品免费一区二区三区四区 | 香蕉视频成人在线观看 | 国产精品久久久久久一级毛片 | 国产一区二区三区四区在线观看 | 一区二区三区久久久久久 | 在线一区二区三区 | 成人av一区二区三区 | 希岛爱理在线 | 欧美日韩在线看 | 草草视频网站 | 97超碰在线播放 | 91精品国产乱码久久久久久久久 | 亚洲高清免费视频 | 欧美一区二区免费 | 情趣视频在线免费观看 | 一区二区视频网站 | 中文日韩在线 | 免费成人高清 | 国产美女永久免费无遮挡 | 欧美bbbxxx| 在线国产一区 | 午夜在线影院 | 国产成人精品999在线观看 | 91在线资源 | 日韩精品一区二区三区四区五区 | 一级毛片免费播放 | 久久亚洲国产精品日日av夜夜 | 国产精品美女久久久久久免费 | av 一区二区三区 | 国产免费观看一区二区三区 | 亚洲精品区| 国产黄色影视 | 国产精品久久久99 | 国产在线观看二区 | 中文字幕高清 | 精品国产一区二区三区久久久蜜月 | 日韩精品专区在线影院重磅 | 日产精品久久久一区二区 | 国产精品久久免费视频 | 曰本人一级毛片免费完整视频 | 欧美激情性国产欧美无遮挡 | 久久se精品一区精品二区 | 综合一区二区三区 | 色在线免费视频 | 99re视频| 三区视频| 亚洲天堂久久 | 91久久精品国产91久久性色tv | 亚洲一区二区三区视频 | 国产一区二区三区久久久 | 成人亚洲视频 | 免费视频一区二区三区在线观看 | www视频在线观看 | 91福利在线导航 | 日本黄色一级电影 | 精品久久久久久久久久久久久久 | 欧美日韩一区二区视频在线观看 | 日韩精品一区二区三区在线 | 亚洲精色 | 色网网站 | 亚洲另类视频 | 久草精品视频 | 亚洲第一男人天堂 | 91精品国产色综合久久不卡98口 | 中文字幕二区 | 黄色天堂在线观看 | 国产在线不卡 | 污片在线免费看 | 久久毛片| 国产精品一区二区三区在线免费观看 | 欧美成人精品激情在线观看 | 国产精品久久久久无码av | 成年人视频免费在线看 | 午夜免费视频 | 777kkk999成人ww | 特黄特色大片免费视频观看 | 在线观看成人小视频 | 色视频一区二区三区 | 国产乱码精品一区二区三区av | 亚洲一区二区在线视频 | www.久久| 激情网五月天 | 亚洲在线视频 | 亚洲第一se情网站 | 亚洲国产精品久久 | 久久成人午夜 | 成年人网站免费在线观看 | 欧洲亚洲精品久久久久 | 中文字幕91 | 成人免费在线观看视频 | 欧美日韩视频一区二区 | 国产精品第一国产精品 | 日本中文字幕一区 | 91爱爱网| 色综合一区 | 在线成人一区 | 日韩欧美国产成人一区二区 | 久久三区| 午夜视频免费 | 九九视频这里只有精品 | 国产精品久久久久久中文字 | 91精品国产综合久久久久久蜜臀 | 日韩中字在线观看 | 三级特黄特色视频 | 日韩一区二区三区在线 | 中文字幕在线观看免费 | 2019亚洲日韩新视频 | 草草网站| 久久亚洲国产 | 午夜社区 | 黄色三级视频 | 亚洲一区二区伦理 | 国产精品成人国产乱一区 | 国产女人高潮视频在线观看 | 中文字幕亚洲欧美 | 日韩欧美国产网站 | 黄色一级免费大片 | 国产精品99久久久久久久久久久久 | 日本午夜影院 | 91免费看片神器 | 国产欧美日韩综合精品一区二区 | 国产伦精品一区二区三区四区视频 | 亚洲人成人一区二区在线观看 | 国产精品一区二区三区四区五区 | 一区二区三区影视 | 91av国产精品| 国产精品成人一区二区 | 国产亚洲二区 | 中文字幕欧美日韩 | 九九成人| 中文字幕在线观看的电影 | 国产一区二区三区在线免费观看 | 91国在线高清视频 | 免费三级电影网站 | 亚洲视频中文字幕 | 久久久久国产一级毛片高清版小说 | 91精品国产一区二区三区蜜臀 | 国产精品不卡一区 | 一级黄色片日本 | 亚洲免费视频大全 | 欧美视频三区 | a黄视频| 精品成人在线 | 亚洲一区二区视频在线观看 | 欧美日韩中文国产一区发布 | 国产精品12| 欧美成人h版在线观看 | 久久久久久亚洲精品 | 毛片免费观看视频 | 日韩欧美综合 | 一区二区三区欧美在线 | 国产ts余喵喵和直男多体位 | 在线看一级片 | 亚洲国产精品久久久 | 日韩精品一区二区在线观看 | 中文字幕一区二区三 | 欧美日韩在线免费观看 | 日韩激情综合网 | 精品成人免费一区二区在线播放 | 色综合国产| 国产精品视频一区二区三区 | 午夜视频网站 | 久久久网站 | 精产国产伦理一二三区 | 亚洲成人av在线播放 | 欧美一区二区三区视频 | 久久国产精品免费一区二区三区 | 色婷婷av久久久久久久 | 波多野结衣一区二区三区中文字幕 | 日韩精品一区二区三区在线观看 | 日韩一区二区三区在线观看 | 久久久精品一区 | 亚州中文字幕蜜桃视频 | 不卡一区 | 国产免费黄视频 | 欧美成人综合在线 | 久久久麻豆 | 一区二区视频在线观看 | 天天操天天曰 | 在线中文字幕第一页 | 久久情趣视频 | 国产免费一区二区 | 国产传媒自拍 | 国产精品成人久久久久 | 国产精品人人做人人爽 | 亚洲国产成人精品女人久久久 | 亚洲成人aaa | 亚洲精品大片 | 成人精品久久久 | 91色在线观看 | 日韩在线国产 | 久在线视频 | 欧美国产综合一区 | 日韩欧美手机在线 | 日韩欧美在线一区 | 亚洲精品一区二区三区在线 | 在线免费观看毛片 | 五月婷婷色| 在线观看亚洲 | 黄色精品| 欧美日韩精品久久 | 亚洲精品一区二区在线观看 | 亚洲视频欧美视频 | 天天摸夜夜摸爽爽狠狠婷婷97 | 一级片视频在线观看 | av成人在线观看 | 亚洲综合精品 | 亚洲综合色自拍一区 | 欧美久久久久久久久久久 | 成人av免费观看 | 欧美日韩中文字幕 | 欧美日韩国产精品一区 | 国产精品一区久久久久 | 91亚洲国产成人久久精品网站 | 国偷自产av一区二区三区 | julia中文字幕久久一区二区 | 亚洲欧美日韩在线一区二区 | 91午夜精品 | 欧美一级二级三级视频 | www.涩涩视频 | 国产一区在线视频 | 久久精品在线观看视频 | 国产中文字幕一区二区三区 | 国产一区av在线 | 狠狠人人 | 美女操av| 91精品国产综合久久久久久丝袜 | 久久久久久精 | 日韩视频一区二区三区 | 国产一级免费在线观看 | 精品免费一区 | 黄a在线看| 国产精品久久久一区二区 | 久久综合久久久 | 黄色毛片免费看 | 色婷婷影院| 国产精品久久久久久久一区探花 | 亚洲精品视频在线看 | 黄色毛片免费看 | 免费一二二区视频 | 国产在线不卡 | av一级久久 | 久久久久久网址 | 天天干夜干| 亚洲成人动漫在线观看 | 欧美与黑人午夜性猛交久久久 | 中文字字幕一区二区三区四区五区 | 成人tv| 天天摸天天看 | 欧美三级网 | 久久综合九色综合欧美狠狠 | 国产日韩在线视频 | 天天网 | 国产一区二区三区免费 | 一区二区精品 | 国产在线观看二区 | 九九久久久 | 久久精品播放 | 国产剧情一区二区 | 蜜臀久久99精品久久久无需会员 | 日韩中文一区 | 日韩一区在线观看视频 | 欧美日韩一区二区在线 | 2019亚洲日韩新视频 | 欧美性猛交一区二区三区精品 | 性一级录像片片视频免费看 | 亚洲成人免费在线观看 | 在线观看中文视频 | 在线视频成人永久免费 | 久久这里只有国产精品 | 天天爱天天草 | 美国黄色毛片女人性生活片 | 91精品国产一区二区三区蜜臀 | 精品久久久久久久久久久久久 | 超碰免费观看 | 伊人色综合久久天天五月婷 | 日本免费三片免费观看 | www.伊人.com| 免费视频久久久久 | 成人二区 | 国产成人免费视频 | 欧美怡红院视频一区二区三区 | 日韩欧美精品一区二区三区 | 久久久精品网站 | 国产综合视频在线观看 | 伊人网在线视频观看 | 欧美亚洲视频 | 日本视频免费高清一本18 | 中国大陆高清aⅴ毛片 | 精品国产一区探花在线观看 | 亚洲精品一区久久久久久 | 一区二区在线视频 | 91精品久久久久久久久久入口 | 91精品一区二区三区久久久久久 | 欧美日韩一区二区三 | 日韩一区二区视频 | 国产精品视频免费播放 | 成人免费精品视频 | 亚洲成人观看 | 亚洲国产成人av好男人在线观看 | 精品日韩在线 | 91久久在线 | 99在线视频精品 | 国产一区二区视频在线观看 | 亚洲狠狠 | 亚洲精品乱码久久久久久蜜桃不卡 | 欧美国产日韩一区 | 亚洲美女网站 | 久热av中文字幕 | 国产一区久久精品 | 国产精品久久久久久中文字 | 女人久久久久久久 | 91麻豆精品久久久久蜜臀 | 国产精品久久久久9999鸭 | 精品国产成人 | 日韩综合 | 日韩爱爱视频 | 国产女爽123视频.cno | 亚洲精品午夜aaa久久久 | ririsao亚洲国产中文 | 天天精品| 欧美视频在线播放 | 成人免费视频在线观看 | 天堂久久精品 | 久久这里只有精品23 | 国产高清一区二区三区 | 久久精品手机视频 | 久久99精品视频 | 久久久久久亚洲 | 国产成人精品一区二区三区视频 | 成人在线观看一区 | 国产依人在线 | 日本一区二区三区四区 | 欧洲亚洲视频 | 精品综合久久 | 夜夜春精品视频高清69式 | 国产精品久久久久久吹潮 | 日韩中文字幕一区 | 成人在线一区二区三区 | 夜夜艹| 天堂va在线高清一区 | 国产做a爰片久久毛片a我的朋友 | 日本午夜视频 | 日韩免费观看视频 | 欧美一二三区在线 | 超级碰在线视频 | 成人欧美一区二区三区在线观看 | 亚洲第1页| 一级黄免费看 | 精品少妇一区二区三区日产乱码 | 奇米色欧美一区二区三区 | 国产精品久久久久久久浪潮网站 | 91九色视频在线 | 国产美女自拍视频 | 免费av在线网 | 在线一区二区三区 | 夜夜天天操 | 久久伊 | 国产精品日韩 | 欧美精品99| 伊人夜夜躁av伊人久久 | 久久久中文 | 日韩欧美在线一区二区 | 不卡的一区二区 | 亚洲精品电影在线一区 | 日韩福利视频导航 | 自拍偷拍在线视频 | 99色在线视频 | 一级大片免费观看 | 久久av网 | 国产成人精品一区二区视频免费 | 亚洲人成人一区二区在线观看 | 成人黄色片网站 | 日韩精品久久久久久 | 91网站在线播放 | 亚洲精品久久久久久一区二区 | 日本黄色毛片 | 大黄网站在线观看 | 91在线免费观看 | 91成人精品 | 亚洲高清免费 | 国产伦精品一区二区三区在线 | 亚洲欧洲一区二区 | 久草视频在线播放 | 久久成人精品视频 | 日韩成人高清 | 精品国产一区二区三区四 | 成人二区 | 国产精品久久二区 | 日本久久久久久 | 99精品九九 | 日韩欧美一级二级 | 日日骚av| 日韩91| 亚洲精品二区 | 日本激情视频在线播放 | 成人在线免费视频 | 日本国产欧美 | 国产高清视频一区二区 | 亚洲国产精品久久久久 | 毛片视频播放 | 亚洲视频区 | 国产精品入口久久 | 亚洲精品国产电影 | 精品一区二区久久久久久久网站 | 美女视频黄a | 精品视频在线视频 | 日韩在线播放欧美字幕 | 国产激情视频网 | 天天亚洲| 国内精品久久精品 | 欧美日韩一区精品 | 成人精品一区二区三区中文字幕 | 综合久久综合久久 | 韩国精品视频在线观看 | 色综合成人 | 亚洲a在线观看 | 高清av网站 | 国产一级毛片国语一级 | 国产精品久久久久久av公交车 | 在线成人av| 亚洲网站视频 | 精品一区二区在线观看 | 国产区福利 | 精品少妇一区二区三区 | 久久久久99 | 久久精品一区二区三区四区 | 国产一区久久 | 九九热在线视频免费观看 | 在线视频中文字幕 | 日操 | 中文字幕第二页 | 女同久久另类99精品国产 | theporn国产在线精品 | 欧美日韩一区二区三区 | 日韩毛片免费视频一级特黄 | 国产精品成人在线观看 | 日韩电影免费在线观看中文字幕 | 涩涩视频在线看 | 一区二区三区亚洲 | a亚洲精品 | 免费的黄视频 | 精品国产18久久久久久二百 | 精品色区 | 天天夜夜操 | 国产精品成人国产乱一区 | 91麻豆精品国产91久久久久久久久 | 国产成人在线播放 | 狠狠躁天天躁夜夜添人人 | 亚洲精品国产第一综合99久久 | 精品在线视频一区 | 欧美成人小视频 | 操人视频网站 | 亚洲一区二区三区在线播放 | 国产精品第一 | 精品一区二区电影 | gogo熟少妇大胆尺寸 | 99亚洲精品 | 亚洲一区二区三 | 91中文字幕网 | 亚洲精品一区二区三区在线播放 | 国产精品高潮呻吟 | 亚洲精品成人 | 艹艹网| 成人h动漫精品一区二区器材 | 亚洲一区二区 | 国产精品亚洲成在人线 | 亚洲成人免费在线 | 日本精品免费 | 成人不卡| 狠狠色狠狠色综合网 | 精品不卡| 91成人在线 | 天堂网中文在线 | 激情91| 美女黄网 | av在线一区二区 | 免费成人毛片 | 一区二区三区免费 | 国产精品久久久久久久久久妇女 | 国产成人精品一区二区三区视频 | 99久久久无码国产精品 | 精品视频一区二区三区在线观看 | 免费xxxx大片国产在线 | 精品视频久久久 | 日韩精品一区二区三区在线观看 | 亚洲欧洲一区二区 | 欧美一级在线观看 | 欧美日韩精品一区二区三区 | 日韩午夜影院 | 自拍偷拍亚洲视频 | 激情91| 国产精品午夜电影 | www.日本三级| 国产免费观看一区二区三区 | 高清国产午夜精品久久久久久 | 在线亚洲观看 | 91精品国产乱码久久久久久 | 成人1区2区 | 九九热欧美 | 亚洲视频免费 | 久久亚洲天堂 | av性色| 国产高清精 | 亚洲日韩欧美一区二区在线 | 96久久久 | 亚洲日本乱码一区两区在线观看 | 中文字幕视频在线 | 毛片精品 | 欧美视频在线播放 | 欧美日韩三级在线 | 日本中文字幕电影 | 精品国产一区二区三区久久久蜜月 | 伊人色综合久久久天天蜜桃 | 亚州中文字幕蜜桃视频 | 久久福利电影 | 亚洲91精品 | 日韩一区二区在线视频 | 国产91久久久久 | 久久久91精品国产一区二区三区 | 天天操网 | 黄免费观看 | av免费资源| 亚洲91精品| 国产精品久久久久久久久久久新郎 | 日韩综合一区 | 国产精品福利网站 | 国产精品一区二区三区99 | 黄a在线观看 | 在线观看日韩 | av av在线 | 国精日本亚洲欧州国产中文久久 | 免费国产视频在线观看 | 午夜国产在线 | av在线免费网址 | 久久久久成人精品 | 久久久av| 伊人网网站 | 欧美久久视频 | 久久精品久久精品 | 国产精品欧美一区二区三区 | 国产成人一区二区三区 | 成人片在线播放 | 国产欧美亚洲精品 | 欧美成人精品一区二区男人看 | 国产一区二区毛片 | 麻豆国产免费 | 国产91麻豆视频 | 国产日韩亚洲欧美 | 天天操天天摸天天干 | 欧美激情一区二区三区在线视频 | 免费一区 |