General documentation: Article directory Github: github.com/black-ant

A. The preface

Where the previous article took stock of SpringIOC: Bean creation main process, this article injects the second major step property

Let’s look at a very common picture, from @Topjava. Cn/article / 139…

1.1 What does attribute injection in this document contain?

PS: I stumbled upon the fact that this article cannot be limited to PopulateBeans, so I will continue to improve the following information in this section, if you are interested!

The main scope of Bean property processing is to inject beans. According to our general understanding, Bean injection mainly includes three injection modes: property/constructor/setter

  • Method one: Through the constructor @Autowired main flow
  • Method 2: @autowired main flow via properties
  • Mode 3: @autowired the main process via setter mode

Method one: Through the constructor @Autowired main flow

@Autowired
public AutowiredService(CommonService commonService, BeanAService beanAService) {
	this.commonService = commonService;
	this.beanAService = beanAService;
}
Copy the code

CreateBeanInstance (beanName, MBD, args) is executed in the doCreateBean method
// As you can see, in BeanWrapper, two Autowired objects are already processed

// This is triggered by the following code in createBeanInstance:Constructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if(ctors ! =null|| mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || ! ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);
}

// autowireConstructor core codeC- ConstructorResolver M- autowireConstructorCopy the code

Method 2: @autowired main flow via properties

As you can see in the figure above, neither of the properties starts loading after createBeanInstance, but we know that the injection of the properties is done before initializeBean to ensure that the initialization method is available.

/ /, when dealing with populateBean to InstantiationAwareBeanPostProcessor processing, which mainly include these

org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
/ /...Finally is the core of AutowiredAnnotationBeanPostProcessor, this we behind populateBean speak in detailCopy the code

Mode 3: setter

/ / way sanhe way two types, the PostProcessor processing, mainly org. Springframework. Beans. Factory. The annotation. AutowiredAnnotationBeanPostProcessor
Copy the code

2. Property injection process

Unlike AutoWired above, what else does populateBean primarily handle?

To better understand the process, make a distinction here that in addition to autowired injection properties, there is an important concept in populateBean called PropertyValues

TODO: There is a big problem with this part, the source of which has never been understood, and most of the reference materials have been skimped on// We'll look at it later in the evening. We guess it's because the old XML way of building objects has a property property
// If there are any clear ones, please mention them. Thank you very much

Copy the code

Let’s take a closer look at the property injection process

2.1 Entry for attribute injection

C - AbstractAutowireCapableBeanFactory M173_05 - doCreateBean (beanName mbdToUse, args) : create Bean object - populateBean: Property Injection Operation -> M173_30Copy the code

2.2 Main process of attribute injection

The main process of injecting properties is in doCreateBean. Recall the concept of circular dependencies. Before populateBean is called, an object has been generated that has not completed the related property injection

First take a look at the properties passed in

populateBean(beanName, mbd, instanceWrapper);

PS: Property injection is done before InitializingBean, so the related initialization method can be used with @Autowired object, more on this later

Property to inject the populateBean logic

The overall logic is divided into 7 steps:

  • Step 1: Processing the empty instance of BeanWrapper. The empty instance must be judged and processed before instantiation
  • Use BeanPostProcessors instead
  • Step 3: Inject properties into the bean
  • Step 4: determine whether registered InstantiationAwareBeanPostProcessors and whether to need to rely on tests
  • Step 5: BeanPostProcessor processing, here is mainly InstantiationAwareBeanPostProcessor processing
  • Step 6: Dependency check
  • Step 7 : applyPropertyValues(beanName, mbd, bw, pvs)

C173- AbstractAutowireCapableBeanFactory
    M173_30- populateBean(String beanName, RootBeanDefinition mbd,BeanWrapper bw)
        P- String beanName
        P- RootBeanDefinition mbd
        P- @Nullable BeanWrapper bw
        1-BeanWrapper empty instance handling: If BeanWrapper is empty and MBD has a value, the empty instance cannot be initialized. Throw a BeanCreationException. If BeanWrapper is empty and MBD has no attribute, Direct return2-Beanpostprocessors? - This is the PostProcesssors last loadopportunity. This method defaults for if-bean initialization when defining a bean. Bean InstantiationAwareBeanPostProcessor - > the FOR - all iterations BeanPostProcessors: getBeanPostProcessors - InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation ? - When the return value isfalseTo stop the entire bean property injection directlyreturnTo skip the property injection operation3- Inject properties to the bean -newMutablePropertyValues(PVS) -- get the PropertyValues of the bean -- PropertyValues PVS = (mbd.haspropertyvalues ()? mbd.getPropertyValues() :null) -- PVS sources-Determine if there are auto-injected annotations -> Auto-injected properties - encapsulate PropertyValues into a MutablePropertyValues object, Property on the object allows for simple operations - > PS: M173_30_3 - by MBD. GetResolvedAutowireMode () name is the difference between injection or type injection - > different types of injection - > PS: M173_30_4 - AUTOWIRE_BY_NAME -- autowireByName(beanName, mbd, bw, newPvs); - AUTOWIRE_BY_TYPE -- autowireByType(beanName, mbd, bw, newPvs);4- determine whether registered InstantiationAwareBeanPostProcessors and whether to need to rely on check (needsDepCheck) - registration: HasInstantiationAwareBeanPostProcessors () - rely on check: MBD getDependencyCheck ()! = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE5- when the step4Indicates that processing by BeanPostProcessor is required, that is, hasInstAwareBpps + BeanPostProcessor is not empty - PVS isnullThrough MBD. GetPropertyValues (); Get a -- iterate over the BeanPostProcessor array,instanceofInstantiationAwareBeanPostProcessor, pre-processing of Bean - PropertyValues = ibp. PostProcessProperties (PVS. bw.getWrappedInstance(), beanName); -- Obtain PropertyValues. - If PropertyValues isnullBy ibp. PostProcessPropertyValues (PVS, filteredPds, bw. GetWrappedInstance (), beanName); Complete build - filteredPds = filterPropertyDescriptorsForDependencyCheck (bw, MBD allowCaching);6- rely on check - filteredPds = filterPropertyDescriptorsForDependencyCheck (bw, MBD allowCaching); - checkDependencies(beanName, mbd, filteredPds, pvs); -- Dependency checking, corresponding to the depends-on attribute7- applyPropertyValues(beanName, mbd, bw, pvs); C175- AbstractBeanDefinition: MutablePropertyValues class M175_01- getResolvedAutowireMode: Get the type of AutowiredCopy the code

PS:M173_30_3 MutablePropertyValues

Allows simple property manipulation and provides constructors to support deep copying and construction from maps

C190- MutablePropertyValues
    F190_01- List<PropertyValue> propertyValueList
    F190_02- Set<String> processedProperties


Copy the code

PS:M173_30_4 was injected through different types

C173- AbstractAutowireCapableBeanFactory M173_10- autowireByName : According to the attribute name, Complete automatic dependency injection - get non-simple properties of Bean objects (objects of non-basic types) FOR- loop through the array of properties, Get related bean by name recursively - add related bean to MutablePropertyValues - registerDependentBean(propertyName, beanName); - Map<String, Set<String>> dependentBeanMap : BeanName - > rely on beanName collection - Map < String, Set the < String > > dependenciesForBeanMap: rely on beanName - > beanName collection -1Get beanName -2Add <canonicalName, <dependentBeanName>> to a dependentBeanMap -3Add < <canonicalName>> to dependenciesForBeanMap M173_11- autowireByType: Do automatic dependency injection based on the attribute type - the overall approach is similar to byName, where the logic is to find the attribute that needs dependency injection and then iteratively find the bean that matches itCopy the code

M173_10 autowireByName source

protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        for (String propertyName : propertyNames) {
            // Check whether the Bean is loaded
            if (containsBean(propertyName)) {
                Object bean = getBean(propertyName);
                pvs.add(propertyName, bean);
                // Register a dependent bean for the given bean so that the given bean can be destroyed before it is destroyed
                registerDependentBean(propertyName, beanName);
                 / /... log
            }
            else {
                / /... log}}}// Pro 1: containsBean details-containsBeanDefinition: -containsBeandefinition: BeanDefinitionMap. Either containsKey (beanName), registerBeanDefinition add - parentBeanFactory. ContainsBean: from the Parent// Pro 2: registerDependentBean logic, which does several things
public void registerDependentBean(String beanName, String dependentBeanName) {
    // Determine the original name and resolve the alias to the canonical name, which is essentially a loop to aliasMap
    String canonicalName = canonicalName(beanName);
        
    // Lock the dependentBeanMap to ensure that multiple threads are unique
    DependentBeanMap: a collection of dependentBean names to dependentbean names
    synchronized (this.dependentBeanMap) {
        Set<String> dependentBeans =this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
        if(! dependentBeans.add(dependentBeanName)) {return; }}DependenciesForBeanMap: a collection of bean names to which I am dependent
    synchronized (this.dependenciesForBeanMap) {
        Set<String> dependenciesForBean =
        this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8)); dependenciesForBean.add(canonicalName); }}// PS: dependentBeanMap and dependenciesForBeanMap
https://blog.csdn.net/xieyinghao_bupt/article/details/109552054

Copy the code

M173_11 autowireByType source

Ps: There are too few cases here at the beginning, I didn’t understand, I turned over the series of notes, and finally figured it out

This section refers to IOC, only part of the logic is added

protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
        // Define the interface to the type conversion method
        // Use a custom TypeConverter to replace the default PropertyEditor mechanism
        TypeConverter converter = getCustomTypeConverter();
        if (converter == null) {
            // If the above interface is null, BeanWrapper will be used directly
            converter = bw;
        }

        Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
        // Get non-simple attributes
        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        // Iterate over the propertyName array
        for (String propertyName : propertyNames) {
            try {
                // Obtain the PropertyDescriptor instance
                PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
                if(Object.class ! = pd.getPropertyType()) {// Probe the set method of the specified property
                    MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                    booleaneager = ! (bw.getWrappedInstance()instanceof PriorityOrdered);
                    DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                    // Parse the value of the attribute specified by beanName and store the name of the parsed attribute in autowiredBeanNames
                    // When an attribute exists over a encapsulated bean, all matching beans will be found and injected
                    Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                    if(autowiredArgument ! =null) {
                        pvs.add(propertyName, autowiredArgument);
                    }
                    // Iterate over the autowiredBeanName array
                    for (String autowiredBeanName : autowiredBeanNames) {
                        // Attribute dependency injectionregisterDependentBean(autowiredBeanName, beanName); } autowiredBeanNames.clear(); }}catch (BeansException ex) {
                throw newUnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex); }}} PS: autowireByType can pass@Bean(initMethod = "initMethod", autowire = Autowire.BY_TYPE)Triggers:Pro 1: PropertyDescriptor objectFunction: PropertyDescriptor describes a property method exported by a Java bean using a pair of accessor methods. GetPropertyDescriptor: gets a PropertyDescriptor for a specific property of the wrapped object// Pro 2 : BeanUtils.getWriteMethodParameter(pd)-method writeMethod = pd.getwritemethod () : gets the Method applied to the value of the write property -> PS:M173_11_01 -new MethodParameter(writeMethod, 0)


// Pro 3 : DependencyDescriptorDescriptor for the specific dependency to be injected. Wraps constructor parameters, method parameters, or fields to allow uniform access to their metadata.Copy the code

PS:M173_11_01 you can see here is the setter method

A question about the default injection type

AUTOWIRE_NO: AUTOWIRE_NO: AUTOWIRE_NO: AUTOWIRE_NO: AUTOWIRE_NO: AUTOWIRE_NO


	public int getResolvedAutowireMode(a) {
		if (this.autowireMode == AUTOWIRE_AUTODETECT) {
			// Work out whether to apply setter autowiring or constructor autowiring.
			// If it has a no-arg constructor it's deemed to be setter autowiring,
			// otherwise we'll try constructor autowiring.Constructor<? >[] constructors = getBeanClass().getConstructors();for(Constructor<? > constructor : constructors) {if (constructor.getParameterCount() == 0) {
					returnAUTOWIRE_BY_TYPE; }}return AUTOWIRE_CONSTRUCTOR;
		}
		else {
			return this.autowireMode; }}Copy the code

ResolveDependency details

ResolveDependency method mainly is called autowireByType, moreover also is involved in AutowiredAnnotationBeanPostProcessor

What it does: resolves the specified dependencies against the beans defined in this factory

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()) {
            return new DependencyObjectProvider(descriptor, requestingBeanName);
        }
        else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
            return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
        }
        else {
            Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                    descriptor, requestingBeanName);
            if (result == null) {
                result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
            }
            returnresult; }}Copy the code

PS: M173_30_5 InstantiationAwareBeanPostProcessor structure

Subinterface functions of BeanPostProcessor: Add a callback function before instantiation and a callback function after instantiation but before explicit property setting or autoliring has occurred. Create agents with special target sources (pooled targets, delayed initialization targets, etc.) to implement additional injection policy features: This interface, in addition to BeanPostProcessor default postProcessBeforeInstantiation, postProcessAfterInstantiation method, There will be an additional method postProcessProperties, postProcessPropertyValues

// public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor
/ / here by inherited hasInstantiationAwareBeanPostProcessors determine whether related objects


/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Pro 1: starting point for configuration
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    / / PS: hasInstantiationAwareBeanPostProcessors attributable to the parent class AbstractBeanFactory
    private volatile boolean hasInstantiationAwareBeanPostProcessors;
    / /...
}


/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Pro 2: Property Settings
// As you can see, the switch is configured in addBeanPostProcessor
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    this.beanPostProcessors.remove(beanPostProcessor);
    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
        this.hasInstantiationAwareBeanPostProcessors = true;
    }
    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
        this.hasDestructionAwareBeanPostProcessors = true;
    }
    this.beanPostProcessors.add(beanPostProcessor);
}

/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
/ / Pro 3: look at the InstantiationAwareBeanPostProcessor calls
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

/ / Step 3: BeanPostProcessors processing, mainly postProcessAfterInstantiation pre-processing
/ / PS: there is only inherited InstantiationAwareBeanPostProcessor class postProcessAfterInstantiation can proceed
/ /...
if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return; }}}}/ /...
/ / Step 5: BeanPostProcessor processing, here is mainly InstantiationAwareBeanPostProcessor processing
for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        / / implementation InstantiationAwareBeanPostProcessor postProcessProperties
        PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                 / / implementation InstantiationAwareBeanPostProcessor postProcessPropertyValues
                pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return; } } pvs = pvsToUse; }}}/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
4: / / Pro postProcessProperties and postProcessPropertyValues rolePostProcessProperties: - at the factory before the application of the attribute value of a given to a given bean for reprocessing, do not need any property descriptors. PostProcessPropertyValues: - Post-process the given attribute values before the factory applies them to the given bean. - allows replacement of the PropertyValues to be applied, usually by creating a new MutablePropertyValues instance based on the original PropertyValues, adding or removing specific valuesCopy the code

2.3 Functions of PropertyValue and applyPropertyValues

Throughout the process, a property called PropertyValue appears repeatedly. Let’s take a look at the past and present

// M173_11 source code
// TODO C173 - AbstractAutowireCapableBeanFactory M173_15 - applyPropertyValues: attributes into operation? - The previous operation is just to complete the acquisition of all injected properties and encapsulate the acquired properties in the instance PVS of PropertyValues? - Here attributes are applied to the bean that has been instantiated1- BeanWrapperImpl.setSecurityContext ? - Set the SecurityContext property of BeanWrapperImpl2- Prepare properties - MutablePropertyValues MPVS -list <PropertyValue> Original3- to obtain attribute set - the original = MPVS. GetPropertyValueList () : / original = Arrays.aslist (pvs.getPropertyValues())// There is an intermediate node: if the configuration is complete, then return
        4- Prepare property - TypeConverter Converter = getCustomTypeConverter() -new BeanDefinitionValueResolver(this, beanName, MBD, Converter) : used to parse unparsed objects - List<PropertyValue> deepCopy =new ArrayList<>(original.size())
        5- For loop List<PropertyValue> original to convert PropertyValue? - Determine whether the property value is converted. Non-mutablepropertyvalues will use the original type directly. - Otherwise, obtain propertyName and originalValue first// Note that Autowired processing is performed here- If the type is Autowired - Method writeMethod = bw.getPropertyDescriptor(propertyName).getwritemethod ()? In the case of Autowired property, get the property descriptor for the particular property of the wrapper object and then get the method applied to write the property value -new DependencyDescriptor(new MethodParameter(writeMethod, 0), true)? - Creates a new descriptor for a method or constructor parameter// Note that the property transformation starts here and is divided into two steps
            5.1- convertedValue = valueResolver.resolveValueIfNecessary ? - Given PropertyValue, return a value that resolves any references to other beans in the factory if necessary5.2- convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter) ? - If writable and not given attribute path indicates index or nested attribute - setConvertedValue + added to4Step List<PropertyValue> deepCopy collection6- Inject the core: set the property values for the property -- bw.setpropertyValues (MPVS);Copy the code

M173_15 applyPropertyValues source code

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        if (pvs.isEmpty()) {
            return;
        }
        // Step 1: Set BeanWrapperImpl's SecurityContext property
        if(System.getSecurityManager() ! =null && bw instanceof BeanWrapperImpl) {
            ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
        }

        // Step 2: Prepare attributes
        MutablePropertyValues mpvs = null;
        List<PropertyValue> original;

        // Step 3: Get the property set
        if (pvs instanceof MutablePropertyValues) {
            mpvs = (MutablePropertyValues) pvs;
             // Return directly after conversion
            if (mpvs.isConverted()) {
                try {
                    bw.setPropertyValues(mpvs);
                    return;
                }
                catch (BeansException ex) {
                    throw new BeanCreationException(
                            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
                }
            }
            original = mpvs.getPropertyValueList();
        }
        else {
            original = Arrays.asList(pvs.getPropertyValues());
        }
        
        // Step 4: Prepare attributes
        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;
        // Step 5: Attribute loop transformation
        for (PropertyValue pv : original) {
            if (pv.isConverted()) {
                deepCopy.add(pv);
            }
            else {
                String propertyName = pv.getName();
                Object originalValue = pv.getValue();
                if (originalValue == AutowiredPropertyMarker.INSTANCE) {
                    Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
                    if (writeMethod == null) {
                        throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
                    }
                    originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
                }
                Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
                Object convertedValue = resolvedValue;
                booleanconvertible = 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 instanceofTypedStringValue && ! ((TypedStringValue) originalValue).isDynamic() && ! (convertedValueinstanceof Collection || ObjectUtils.isArray(convertedValue))) {
                    pv.setConvertedValue(convertedValue);
                    deepCopy.add(pv);
                }
                else {
                    resolveNecessary = true;
                    deepCopy.add(newPropertyValue(pv, convertedValue)); }}}if(mpvs ! =null && !resolveNecessary) {
            mpvs.setConverted();
        }

        // Step 6: Inject the core
        try {
            bw.setPropertyValues(new MutablePropertyValues(deepCopy));
        }
        catch (BeansException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Error setting property values", ex); }}Copy the code

conclusion

It looks like a long time, but after looking back at the series, I feel that there are still a lot of places I haven’t understood, and I have time to fill in the pit later

It’s too late to beat the curls. Go to bed

The appendix

Appendix I: M173_30 populateBean core code

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        // The empty instance of BeanWrapper must be determined and processed before instantiation
        if (bw == null) {
            // If BeanWrapper is empty and MBD has a value, the empty instance cannot be initialized, throw BeanCreationException
            if (mbd.hasPropertyValues()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                // If BeanWrapper is empty and MBD has no attribute, return
                return; }}// isSynthetic: returns whether the bean definition is "synthetic", i.e. not defined by the application itself
        / / hasInstantiationAwareBeanPostProcessors: hold InstantiationAwareBeanPostProcessor bean
        if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {// Loop all
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                   / / here will only handle InstantiationAwareBeanPostProcessor
                    if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return; }}}}// Get the value of the bean property
        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
        // Check whether there is an auto-injected annotation -> Auto-injected attribute
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            // Encapsulate PropertyValues into a MutablePropertyValues object that allows simple manipulation of properties -> PS:M173_30_3
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            / / by MBD. GetResolvedAutowireMode () difference is that the name injection or type injection - > different types of injection - > PS: M173_30_4
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
       
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
            pvs = newPvs;
        }

        / / determine whether registered InstantiationAwareBeanPostProcessors and whether to need to rely on to check (needsDepCheck)
        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        booleanneedsDepCheck = (mbd.getDependencyCheck() ! = AbstractBeanDefinition.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) {
            if (filteredPds == null) {
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            // The dependency check corresponds to the depends-on attribute
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }

        if(pvs ! =null) {
            // Apply attributes to the beanapplyPropertyValues(beanName, mbd, bw, pvs); }}Copy the code

Appendix II: autowireConstructor Main method TODO

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
            @NullableConstructor<? >[] chosenCtors,@Nullable Object[] explicitArgs) {

        BeanWrapperImpl bw = new BeanWrapperImpl();
        this.beanFactory.initBeanWrapper(bw); Constructor<? > constructorToUse =null;
        ArgumentsHolder argsHolderToUse = null;
        Object[] argsToUse = null;

        if(explicitArgs ! =null) {
            argsToUse = explicitArgs;
        }
        else {
            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) {
                argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true); }}if (constructorToUse == null || argsToUse == null) {
            // 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(...);
                }
            }

            if (candidates.length == 1 && explicitArgs == null&&! mbd.hasConstructorArgumentValues()) { Constructor<? > uniqueCandidate = candidates[0];
                if (uniqueCandidate.getParameterCount() == 0) {
                    synchronized (mbd.constructorArgumentLock) {
                        mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                        mbd.constructorArgumentsResolved = true;
                        mbd.resolvedConstructorArguments = EMPTY_ARGS;
                    }
                    bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
                    returnbw; }}// Need to resolve the constructor.
            booleanautowiring = (chosenCtors ! =null ||
                    mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.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);
            }

            AutowireUtils.sortConstructors(candidates);
            intminTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<? >> ambiguousConstructors =null;
            LinkedList<UnsatisfiedDependencyException> causes = null;

            for(Constructor<? > candidate : candidates) {int parameterCount = candidate.getParameterCount();

                if(constructorToUse ! =null&& argsToUse ! =null && argsToUse.length > parameterCount) {
                    // Already found greedy constructor that can be satisfied ->
                    // do not look any further, there are only less greedy constructors left.
                    break;
                }
                if (parameterCount < minNrOfArgs) {
                    continue; } ArgumentsHolder argsHolder; Class<? >[] paramTypes = candidate.getParameterTypes();if(resolvedValues ! =null) {
                    try {
                        String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
                        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) {
                        // 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(parameterCount ! = 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 = newLinkedHashSet<>(); 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 newBeanCreationException(...) ; }else if(ambiguousConstructors ! =null && !mbd.isLenientConstructorResolution()) {
                throw newBeanCreationException(...) ; }if (explicitArgs == null&& argsHolderToUse ! =null) { argsHolderToUse.storeCache(mbd, constructorToUse); } } Assert.state(argsToUse ! =null."Unresolved constructor arguments");
        bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
        return bw;
    }
Copy the code

Appendix III: Injection timing of @value


TODO

Copy the code