Spring IOC series learning notes 10: createBean method

Original address programmer Jiong Hui boss

preface

Go ahead Explanation of getBean Enter the createBean method.

Code block 1: createBean

	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		1,analysis beanName Corresponding bean Type, for example com.zgf.service.impl.AccountServiceImpl
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			2,resolvedClass Not empty&&mbd of beanClass no Class type&&mbd of beanClassName If it is not empty, then mbd of beanClass Saved is class of Name
			Copy and replace mbd Subsequent operations
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			3,use InstantiationAwareBeanPostProcessor Create a proxy bean Intercept and return to'short circuit'effect.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			4,Really create bean Method of
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			5,return bean example
			return beanInstance;
		}
		catch (BeanCreationException ex) {
			// A previously detected exception with proper bean creation context already...
			throw ex;
		}
		catch (ImplicitlyAppearedSingletonException ex) {
			// An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

3. Create a proxy bean with instantiaawarebeanpostprocessor to intercept and return, so as to achieve the effect of "short circuit". See code block II
4. See code block 3 for the method of creating bean s

Code block 2: resolvebeforeinstance

	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			 1,mbd Not synthetic&&BeanFactory Exist in InstantiationAwareBeanPostProcessors Interface
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					2,Preprocessing
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						3,Post processing
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			4,If bean If it is not empty, the beforeInstantiationResolved Assign as true,Before instantiation, the representation has been resolved
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

Before instantiation, execute the postProcessBeforeInstantiation method of instantiaawarebeanpostprocessor, which can return the proxy of the bean instance, thus skipping the default instantiation process of Spring.

Code block 3: doCreateBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		1,bean Packaging class
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			1.1,judge beanName Is it factoryBean,If yes, the removal is incomplete bean Cache of
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			2,If not factoryBean Then create beanName Packaging class
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		3.1,obtain bean example
		final Object bean = instanceWrapper.getWrappedInstance();
		3.2,obtain bean Instance type of
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			3.3,If bean If the instance type is not empty, set the instance type to mbd
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					4.1,MergedBeanDefinitionPostProcessor Post processing of. Modification is allowed bean
					4.2,@Autowired It's officially pre parsed here
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		5.1,judge bean Early circular reference in advance,Early exposure.
		5.2,mbd It's a single case&&Allow circular dependencies&&current bean Being created
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			6.1,getEarlyBeanReference: utilize SmartInstantiationAwareBeanPostProcessor Post processing return of bean An earlier reference of the. If not, it returns bean itself
			6.2,Early exposure bean,Add to singleton factory to resolve circular references
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			7,Attribute filling
			populateBean(beanName, mbd, instanceWrapper);
			8,initialization bean
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}
		9.1,If early exposure is allowed, perform a cyclic dependency check
		if (earlySingletonExposure) {
			9.2,earlySingletonReference Not in case of circular dependency null
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					9.3,If you are initializing bean It didn't change at the time bean Object, the previous circular reference is not affected
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					9.4,If bean If it is changed during initialization, the original circular reference will be affected, because the referenced old data needs to be eliminated and the latest data will be referenced bean object
					9.5,Get depends on the current beanName All of bean of Name array
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						9.6,Try removing these bean Because of these bean Dependent bean Has been enhanced, they rely on bean Equivalent to dirty data
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							9.7,Remove failed add to actualDependentBeans in
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						9.8,If the removal fails, an exception is thrown because it exists bean Dependent on "dirty data"
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			10,Register for destruction bean,There are three types of destruction operations: custom destroy Methods DisposableBean Interface DestructionAwareBeanPostProcessor
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}
		11,Return created bean
		return exposedObject;
	}

The real method of creating bean s is the core method of this series. It is relatively complex and needs to be read repeatedly.
2. If it is not factoryBean, create the wrapper class of beanName. See code block 4.

Code block 4: createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		1,analysis bean Type information of
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			2,If bean Type is empty&&beanClass Not public class&&Access by non-public classes is not allowed
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}
		3, Yes no bean of Supplier Interface, if any, is created through callback bean
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
		4,If the factory method is not empty, an instance is created using the factory method
		if (mbd.getFactoryMethodName() != null)  {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		5.1,resolved Whether the constructor has resolved the flag; autowireNecessary Whether automatic assembly is required
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				5.2,The constructor or factory method has been resolved
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				6.1,Should bean The constructor has been parsed and needs to be automatically assembled. Use constructor automatic injection for instantiation
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				6.2,Should bean The constructor has been parsed and does not need to be automatically assembled. The default constructor is used for instantiation
				return instantiateBean(beanName, mbd);
			}
		}

		// Need to determine the constructor...
		7.1,Get bean Candidate constructor for
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			7.2,ctors Not empty||mbd The injection method is AUTOWIRE_CONSTRUCTOR||mbd Constructor parameters defined||Dominant structural parameters args Not empty
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// No special handling: simply use no-arg constructor.
		8.If it is not satisfied, the default constructor is used for initialization
		return instantiateBean(beanName, mbd);
	}
  1. If you inherit the Supplier interface, create a bean instance through the Supplier.
  2. If factoryMethodName exists in RootBeanDefinition
    Property, or if factory method is configured in the configuration file, Spring will try to use the instantiateUsingFactoryMethod method to generate Bean instances according to the configuration in RootBeanDefinition. It should be noted that if the method in a class is modified by @ Bean annotation, Spring will encapsulate it into a ConfigurationClassBeanDefinition. At this time, factoryMethodName is also assigned. Therefore, the instantiateUsingFactoryMethod method will also be called to complete the method call through reflection and inject the results into the Spring container.
  3. Instead of the above two methods, try to instantiate using the constructor. First, check whether the bean has a constructor cache. Here, the resolvedconstructorfactorymethod cache is used.
  4. If the cache exists, if automatic assembly is required, the autowireConstructor method is used for instance. On the contrary, the default instantiateBean method is used. (autowireConstructor with parameters and instantiateBean without parameters)
  5. The cache does not exist. First, obtain the candidate constructor through the determineconstructionsfrombeanpostprocessors method and make the final selection through autowireConstructor or instantiateBean. The candidate constructors are selected in the autowireConstructor, and the most appropriate constructors are selected to build beans. If the parsed constructors are cached, the parsed constructors are directly used to create beans without election.
    6.1. See code block 5 for automatic constructor injection
    7.1. See code block 6 for obtaining candidate constructors

Code block 5: determineconstructors frombeanpostprocessors

	protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
			throws BeansException {

		if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
			1,Traverse all BeanPostProcessor
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					2.call SmartInstantiationAwareBeanPostProcessor of determineCandidateConstructors method,
                 	This method can return the beanClass Candidate constructor for
                 	For example: use@Autowire If the annotation modifies the constructor, the constructor will be modified here AutowiredAnnotationBeanPostProcessor find
					Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
					if (ctors != null) {
						3.If ctors If it is not empty, no other operations will be performed SmartInstantiationAwareBeanPostProcessor
						return ctors;
					}
				}
			}
		}
		return null;
	}

2. Call the determineCandidateConstructors method of smartinstantiaawarebeanpostprocessor, which can return the candidate constructor to be used for beanClass. If @ Autowire annotation is used to modify the constructor, the constructor will be found here by AutowiredAnnotationBeanPostProcessor. This content will be introduced separately in the article introducing @ Autowire later.

Code block 6: autowireConstructor

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

		1,establish bean Packaging class
		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);
		2.1,Final instantiated constructor
		Constructor<?> constructorToUse = null;
		2.2,Parameter holder of final instantiation
		ArgumentsHolder argsHolderToUse = null;
		2.4,Final instantiated constructor parameter array
		Object[] argsToUse = null;
		3,If an argument to the constructor is explicitly specified, it is used
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			4.1,Trying to get constructor parameters from cache
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				4.2,Get the resolved constructor or factory method from the cache
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				4.3,If constructorToUse Not empty&&Constructor arguments resolved
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					4.4,Get the resolved constructor parameters
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						4.5,If argsToUse If it is empty, get the constructor parameters that are ready to be resolved
						Here if mbd.constructorArgumentsResolved by true When, the constructor parameter must have been resolved or ready to be resolved, and there must be a cached parameter
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			if (argsToResolve != null) {
				4.6,Parse prepared constructor parameters
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
			}
		}
		5.1,If there is no constructor in the cache
		if (constructorToUse == null) {
			// Need to resolve the constructor.
			5.2,If chosenCtors Not empty||autowireMode yes AUTOWIRE_CONSTRUCTOR,Automatic injection is required
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;
			5.3,Number of constructor parameters
			int minNrOfArgs;
			if (explicitArgs != null) {
				5.4,If the construction parameter is explicitly specified, the length is obtained
				minNrOfArgs = explicitArgs.length;
			}
			else {
				5.5,mbd Construction parameter value of indexedArgumentValues Cache is with index Value of   genericArgumentValues Cached values are generic
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				5.6,Value of construction parameter after bearing analysis
				resolvedValues = new ConstructorArgumentValues();
				5.7,analysis mbd And returns the number of parameters
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
	            // Note: parsing the constructor parameter values in mbd here mainly deals with the parameters injected by the constructor defined in xml,
	            // However, if we directly modify the constructor through @ Autowire annotation, mbd does not have these parameter values
			}

			// Take specified constructors, if any.
			6.1,Get all candidate constructors, if chosenCtors If it is not empty, it is a candidate
			Constructor<?>[] candidates = chosenCtors;
			if (candidates == null) {
				Class<?> beanClass = mbd.getBeanClass();
				try {
					6.2,If the constructor can be accessed by non-public, get all, otherwise only get the common constructor
					candidates = (mbd.isNonPublicAccessAllowed() ?
							beanClass.getDeclaredConstructors() : beanClass.getConstructors());
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Resolution of declared constructors on bean Class [" + beanClass.getName() +
							"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
				}
			}
			7,Sort the candidate constructors, public Constructor parameters from more to less, non public Parameters from more to less
			AutowireUtils.sortConstructors(candidates);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			8.Ambiguous constructors, two constructors with equal weight and minimum tangent
			Set<Constructor<?>> ambiguousConstructors = null;
			LinkedList<UnsatisfiedDependencyException> causes = null;
			9.1,Traverse all candidate constructors
			for (Constructor<?> candidate : candidates) {
				Class<?>[] paramTypes = candidate.getParameterTypes();
				9.2,A suitable constructor has been found&&If the number of constructor parameters is greater than the number of current constructor parameters, jump out of the loop
				Because the appropriate constructor has been found and the number of parameters is in descending order, there is no need to compare
				if (constructorToUse != null && argsToUse.length > paramTypes.length) {
					// Already found greedy constructor that can be satisfied ->
					// do not look any further, there are only less greedy constructors left.
					break;
				}
				9.3,The number of current candidate construction parameters is less than the required construction parameters. It is definitely inappropriate to skip directly
				if (paramTypes.length < minNrOfArgs) {
					continue;
				}

				ArgumentsHolder argsHolder;
				if (resolvedValues != null) {
					10.1, resolvedValues Not empty
					try {
						10.2,Analytical use ConstructorProperties Constructor parameters for annotations
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
						if (paramNames == null) {
							10.3,Get parameter name parser
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								10.4,Use the parameter name parser to get the parameter name of the constructor currently traversed
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						10.5,It mainly resolves the parameters required by the constructor or factory method through the parameter type and parameter name (if the parameters are other parameters) bean,The dependent will be resolved bean)
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring);
					}
					catch (UnsatisfiedDependencyException ex) {
						if (this.beanFactory.logger.isTraceEnabled()) {
							this.beanFactory.logger.trace(
									"Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
						}
						// Swallow and try next constructor.
						if (causes == null) {
							causes = new LinkedList<>();
						}
						causes.add(ex);
						continue;
					}
				}
				else {
					// Explicit arguments given -> arguments length must match exactly.
					11.1,If resolvedValues Null. The current function parameter is not equal to the explicitly specified parameter. Skip and continue to find
					if (paramTypes.length != explicitArgs.length) {
						continue;
					}
					11.2,Construct with explicit parameters ArgumentsHolder
					argsHolder = new ArgumentsHolder(explicitArgs);
				}
				12.1,take argsHolder Parameters and paramTypes Compare and calculate paramTypes Weight value of type difference
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// Choose this constructor if it represents the closest match.
				12.2,The smaller the weight value of type difference,It means that the more the constructor matches, this constructor will be selected
				if (typeDiffWeight < minTypeDiffWeight) {
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					12.3,If a candidate with a smaller weight value appears, the ambiguousConstructors Empty, allowing candidates with the same weight value to exist before
					ambiguousConstructors = null;
				}
				12.4,If there are two candidates with the same weight value and the smallest weight value that has been traversed at present
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						12.5,Add to ambiguousConstructors
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}

			if (constructorToUse == null) {
				if (causes != null) {
					If no matching constructor is found, exception handling is performed
					UnsatisfiedDependencyException ex = causes.removeLast();
					for (Exception cause : causes) {
						this.beanFactory.onSuppressedException(cause);
					}
					throw ex;
				}
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Could not resolve matching constructor " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
			}
			else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
				If a matching constructor is found, but more than one exists( ambiguousConstructors (not null) && If the mode of the parsing constructor is strict mode, an exception is thrown
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Ambiguous constructor matches found in bean '" + beanName + "' " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
						ambiguousConstructors);
			}

			if (explicitArgs == null) {
				13,Put the parsed constructor and parameters into the cache
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		try {
			final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
			Object beanInstance;
			14,Instantiate according to the instantiation strategy and the obtained constructor and constructor parameters bean. 
			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);
			}
			15,Set instance to wrapper class return
			bw.setBeanInstance(beanInstance);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean instantiation via constructor failed", ex);
		}
	}

General process:

  1. Whether the construction parameter is explicitly specified. If it is explicitly specified, explicatargs is used as the construction parameter.
  2. If the construction parameters are not specified, they will be obtained from the cache, that is, they will be resolved from resolvedConstructorArguments and preparedConstructorArguments.
  3. If the constructor is not obtained from the cache, the chosenCtors of the input parameter will be used as the candidate constructor. If chosenCtors is null, the candidate constructor will be obtained through reflection.
  4. For candidates, the number of priority parameters of public constructor is in descending order, and the number of parameters of non-public constructor is in descending order
    The purpose of regular sorting is to judge whether there is an appropriate constructor more quickly when retrieving later.
  5. Traverse the constructor and select the constructor with the smallest matching difference to create the bean instance.
    5.7. Analyze the parameters of the constructor of mbd and return the number of parameters. See code block 7
    10.5. Mainly resolve the parameters required by the constructor or factory method through the parameter type and parameter name (if the parameter is other beans, it will resolve the dependent beans). See code block 8
    13. Put the parsed constructor and parameters into the cache, see the code block

Code block 7: resolveConstructorArguments

private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
                                        ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
 
    // 1. Build bean definition value parser
    TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
    TypeConverter converter = (customConverter != null ? customConverter : bw);
    BeanDefinitionValueResolver valueResolver =
            new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
 
    // 2.minNrOfArgs is initialized to the sum of indexedArgumentValues and genericArgumentValues
    int minNrOfArgs = cargs.getArgumentCount();
    // 3. Traverse and parse the parameter value with index
    for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
        int index = entry.getKey();
        if (index < 0) {
            // index starts from 0 and cannot be less than 0
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Invalid constructor argument index: " + index);
        }
        // 3.1 if the index is greater than minNrOfArgs, modify minNrOfArgs
        if (index > minNrOfArgs) {
            // The index starts from 0 and increases in order, so when the index with parameters = 5, it means that the method has at least 6 parameters
            minNrOfArgs = index + 1;
        }
        ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
        // 3.2 analytical parameter values
        if (valueHolder.isConverted()) {
            // 3.2.1 if the parameter value has been converted, add index and valueHolder directly to the indexedArgumentValues property of resolvedValues
            resolvedValues.addIndexedArgumentValue(index, valueHolder);
        } else {
            // 3.2.2 if the value has not been converted, convert it first
            Object resolvedValue =
                    valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
            // 3.2.3 use the converted resolvedValue to build a new ValueHolder
            ConstructorArgumentValues.ValueHolder resolvedValueHolder =
                    new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
            // 3.2.4 save the valueholder before conversion to the source attribute of the new valueholder
            resolvedValueHolder.setSource(valueHolder);
            // 3.2.5 add index and new ValueHolder to indexedArgumentValues property of resolvedValues
            resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
        }
    }
 
    // 4. Traverse and parse general parameter values (without index)
    for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
        if (valueHolder.isConverted()) {
            // 4.1 if the parameter value has been converted, add valueHolder directly to the genericArgumentValues attribute of resolvedValues
            resolvedValues.addGenericArgumentValue(valueHolder);
        } else {
            // 4.2 if the value has not been converted, convert it first
            Object resolvedValue =
                    valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
            // 4.3 use the converted resolvedValue to build a new ValueHolder
            ConstructorArgumentValues.ValueHolder resolvedValueHolder =
                    new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
            // 4.4 save the valueholder before conversion to the source attribute of the new valueholder
            resolvedValueHolder.setSource(valueHolder);
            // 4.5 add a new ValueHolder to the genericArgumentValues property of resolvedValues
            resolvedValues.addGenericArgumentValue(resolvedValueHolder);
        }
    }
    // 5. Return the number of constructor parameters
    return minNrOfArgs;
}

Code block 8: createArgumentArray

private ArgumentsHolder createArgumentArray(
			String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
			BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
			boolean autowiring) throws UnsatisfiedDependencyException {

		TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
		TypeConverter converter = (customConverter != null ? customConverter : bw);
		1,Used to store matching parameters
		ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
		Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		2.1,Traversal class construction parameter array
		for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
			2.2,Get the current parameter type
			Class<?> paramType = paramTypes[paramIndex];
			2.3,Get the current parameter name
			String paramName = (paramNames != null ? paramNames[paramIndex] : "");
			// Try to find matching constructor argument value, either indexed or generic.
			ConstructorArgumentValues.ValueHolder valueHolder = null;
			if (resolvedValues != null) {
				2.4,Verify the parameter name and type of the current traversal, index,Whether it matches the configuration (i.e. comparison) xml Configuration parameters and construction methods in the class)
				valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
				// If we couldn't find a direct match and are not supposed to autowire,
				// let's try the next generic, untyped argument value as fallback:
				// it could match after type conversion (for example, String -> int).
				2.5,If no match is found&&It's not automatic assembly. Try demotion, for example String matching int type
				if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
					valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
				}
			}
			if (valueHolder != null) {
				// We found a potential match - let's give it a try.
				// Do not consider the same value definition multiple times!
				usedValueHolders.add(valueHolder);
				3.1,Get the original value
				Object originalValue = valueHolder.getValue();
				3.2,Used to store the converted value
				Object convertedValue;
				if (valueHolder.isConverted()) {
					3.3,If it has been converted, get the converted value
					convertedValue = valueHolder.getConvertedValue();
					3.4,Store in args The corresponding position is used as the preliminary parameter
					args.preparedArguments[paramIndex] = convertedValue;
				}
				else {
					3.5,Without conversion, encapsulate the method (constructor here) and parameter index into MethodParameter(MethodParameter Is a tool class that encapsulates method and parameter indexes)
					MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
					try {
						3.5,Convert
						convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
					}
					catch (TypeMismatchException ex) {
						throw new UnsatisfiedDependencyException(
								mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
								"Could not convert argument value of type [" +
										ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
										"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
					}
					Object sourceHolder = valueHolder.getSource();
					if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
						3.5,If sourceHolder yes ConstructorArgumentValues.ValueHolder The representation of the type has not been resolved
						Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
						3.6,Flag needs to be resolved
						args.resolveNecessary = true;
						3.7,Save to preliminary parameters
						args.preparedArguments[paramIndex] = sourceValue;
					}
				}
				3.8,take convertedValue As args stay paramIndex Parameters of position
				args.arguments[paramIndex] = convertedValue;
				3.9,take originalValue As args stay paramIndex Original parameters of position
				args.rawArguments[paramIndex] = originalValue;
			}
			else {
				4.1,There are no matching parameters, valueHolder by null
				MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
				// No explicit match found: we're either supposed to autowire or
				// have to fail creating an argument array for the given constructor.
				4.2,If it is not automatic injection, an exception will be thrown directly, because there are two ways to configure construction parameters, automatic injection and automatic injection xml The non automatic injection configuration has been resolved earlier xml The configuration now resolves automatic injection
				if (!autowiring) {
					throw new UnsatisfiedDependencyException(
							mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
							"Ambiguous argument values for parameter of type [" + paramType.getName() +
							"] - did you specify the correct bean references as arguments?");
				}
				try {
					4.3,If the parameter is used for automatic assembly, the result returned is bean Instance object
                	 For example:@Autowire Modify the constructor and automatically inject the parameters in the constructor bean Just deal with it here
					Object autowiredArgument =
							resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter);
					4.4,Assign the parameters parsed through automatic assembly to args
					args.rawArguments[paramIndex] = autowiredArgument;
					args.arguments[paramIndex] = autowiredArgument;
					args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
					args.resolveNecessary = true;
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(
							mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
				}
			}
		}
		5.1,Dependent bean Register dependencies
		for (String autowiredBeanName : autowiredBeanNames) {
			this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
			if (this.beanFactory.logger.isDebugEnabled()) {
				this.beanFactory.logger.debug("Autowiring by type from bean name '" + beanName +
						"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
						" to bean named '" + autowiredBeanName + "'");
			}
		}

		return args;
	}

4.3. In case of automatic assembly, call the method used to parse the automatic assembly parameters, and the returned result is the dependent bean instance object. See code block 9

Code block 9: resolveAutowiredArgument

protected Object resolveAutowiredArgument(
        MethodParameter param, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) {
 
     1,If the parameter type is InjectionPoint
    if (InjectionPoint.class.isAssignableFrom(param.getParameterType())) {
         1,1 Get the current InjectionPoint(Stores the parameter information of the dependent method currently being resolved, DependencyDescriptor)
        InjectionPoint injectionPoint = currentInjectionPoint.get();
        if (injectionPoint == null) {
             1,2 current injectionPoint If it is empty, an exception will be thrown: there is no available InjectionPoint
            throw new IllegalStateException("No current InjectionPoint available for " + param);
        }
         1,3 Returns the current InjectionPoint
        return injectionPoint;
    }
     2,Resolve specified dependencies, DependencyDescriptor: take MethodParameter The method parameter index information is encapsulated into DependencyDescriptor
    return this.beanFactory.resolveDependency(
            new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
}

2. See code block 10 for resolving the specified dependency

Code block 10: resolveDependency

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		1,Optional Special handling of class injection
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		2,ObjectFactory perhaps ObjectProvider Treatment of
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		3,Jsr330ProviderFactory Class processing
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
			4,For the processing of general classes, the above three processing methods will actually follow the general processing method in the end
			4.1,Delayed loading
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
				4.2,Not delayed loading, parsing returns bean example
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

General process:

  1. Optional: JDK8 provides an API. It is mainly used to set dependency as non mandatory dependency, i.e. descriptor required=false.
  2. Deferred dependency injection support: ObjectFactory, ObjectProvider, javax inject. There is no essential difference between providers.
  3. Another support for delayed injection - @ Lazy attribute.
  4. Find dependencies by type - doResolveDependency.

4.2. Instead of delayed loading, see code block 11 for the bean instance returned by parsing

Code block 11: doResolveDependency

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			1,Directly through getBean Get by
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}
			2,Get the type of the current field parameter
			Class<?> type = descriptor.getDependencyType();
			2.1,obtain@Value Annotation value
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					2.2,analysis String Value of, such as parsing placeholders, etc
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				2.3,Convert to the required type and return, for example @Value("clown ")  Then it returns"clown "
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				return (descriptor.getField() != null ?
						converter.convertIfNecessary(value, type, descriptor.getField()) :
						converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
			}
			3,Resolve complex types, such as: Array,List,Map,Collection etc.
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}
			4,If it is not the above type, find the required type bean example, map(key: bean Your name; value: bean An instance or bean Instance type)
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			4.1,If require Attribute is true,And found a match Bean If it is empty, an exception is thrown
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				4.2,If require Attribute is false,And found a match Bean If it is empty, return null
				return null;
			}
			5.1,Final instance name
			String autowiredBeanName;
			5.2,Final instance or instance type
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {
				5.3,If the candidate instance is not unique, the best one needs to be selected and returned name
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(type, matchingBeans);
					}
					else {
						// In case of an optional Collection/Map, silently ignore a non-unique case:
						// possibly it was meant to be an empty collection of multiple regular beans
						// (before 4.3 in particular when we didn't even look for collection beans).
						return null;
					}
				}
				5.4,Get autowiredBeanName of bean Instance or bean Instance type
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				5.5,If only, use this directly
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				6.1,Will depend on beanName Add autowiredBeanNames in
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {
				7,If instanceCandidate Instance type, resolve to bean example
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

technological process:

  1. Get directly through getBean
  2. @Value annotation processing scenario
  3. Collection dependent query
  4. Single dependent query
    4. Find the bena instance of bena candidate, see code block 12
    5.3 if the candidate instance is not unique, the best one needs to be selected. See code block 14

Code block 12: findAutowireCandidates

protected Map<String, Object> findAutowireCandidates(
			@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
		1,Gets all of the parameters of the current parameter type beanNname
		String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
				this, requiredType, true, descriptor.isEager());
		Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
		2,from spring Internal Cache resolvableDependencies obtain
		for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
			if (autowiringType.isAssignableFrom(requiredType)) {
				2.1,judge autowiringType and requiredType Does the type match
				2.2,obtain bean example
				Object autowiringValue = this.resolvableDependencies.get(autowiringType);
				2.3,Resolve the given auto assembly value according to the given required type
				autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
				if (requiredType.isInstance(autowiringValue)) {
					2.4,If autowiringValue yes requiredType Type is put directly into result,here value by bena example
					result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
					break;
				}
			}
		}
		3.1,Traverse from container beanName
		for (String candidate : candidateNames) {
			3.2,Not self reference&&Qualified as a candidate
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
				3.3,Add candidate to result in
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}
		4,The above instances are not obtained and put into result in&&If it is not a complex type, use degraded matching
		if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
			// Consider fallback matches if the first pass failed to find anything...
			DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
			for (String candidate : candidateNames) {
				if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
			5,If the degraded matching result is still empty, self reference is considered
			if (result.isEmpty()) {
				// Consider self references as a final pass...
				// but in the case of a dependency collection, not the very same bean itself.
				for (String candidate : candidateNames) {
					if (isSelfReference(beanName, candidate) &&
							(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
							isAutowireCandidate(candidate, fallbackDescriptor)) {
						addCandidateEntry(result, candidate, descriptor, requiredType);
					}
				}
			}
		}
		return result;
	}

The isAutowireCandidate method has three rules for filtering candidate objects: ① bd.autowirecandidate = true - > ② generic matching - > ③ @ Qualifier.
3.3. Add the candidate to the result. See code block 13

Code block 13: addCandidateEntry

private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
                               DependencyDescriptor descriptor, Class<?> requiredType) {
    // 1. If the descriptor is a MultiElementDescriptor, the type | candidateName already exists in the singletonObjects cache
    if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
        // 2.1 resolveCandidate: get the corresponding bean instance through candidate name
        // 2.2 add the mapping of beanname - > bean instance to candidates (in this case, value is bean instance)
        candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
    } else {
        // 3. Add the mapping of bean name - > bean instance type to candidates (at this time, the value is the bean instance type)
        candidates.put(candidateName, getType(candidateName));
    }
}

Return to code block 11 5.3 and enter code block 14 to select the best candidate.

Code block 14: determineAutowireCandidate

protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
		Class<?> requiredType = descriptor.getDependencyType();
		1,according to@Primary Annotation to select the optimal solution
		String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
		if (primaryCandidate != null) {
			return primaryCandidate;
		}
		2,according to@Priority Select the optimal solution
		String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
		if (priorityCandidate != null) {
			return priorityCandidate;
		}
		// Fallback
		3,If the optimal solution cannot be selected through the above two steps, the most basic strategy is used
		for (Map.Entry<String, Object> entry : candidates.entrySet()) {
			String candidateName = entry.getKey();
			Object beanInstance = entry.getValue();
			3.1,containsValue: First, if this beanInstance Already by Spring If you have registered a dependency, you can use it directly beanInstance As the optimal solution
			3.2,atchesBeanName: If you have not registered this beanInstance The dependency of the parameter is matched according to the parameter name
			if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
					matchesBeanName(candidateName, descriptor.getDependencyName())) {
				return candidateName;
			}
		}
		return null;
	}


	protected boolean matchesBeanName(String beanName, String candidateName) {
    // candidateName is equal to beanName 𞓜 beanName has an alias that is equal to candidateName, then true is returned
    return (candidateName != null &&
            (candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName)));
}

Returning to code block 6, 13 enters code block 15 and puts the parsed constructor and parameters into the cache

Code block 15: storeCache

public void storeCache(RootBeanDefinition mbd, Object constructorOrFactoryMethod) {
    synchronized (mbd.constructorArgumentLock) {
        // Put the constructor or factory method into the resolvedconstructorfactorymethod cache
        mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
        // Constructor arguments resolved is marked as resolved
        mbd.constructorArgumentsResolved = true;
        if (this.resolveNecessary) {
            // If the parameter needs to be resolved, put preparedArguments into the preparedConstructorArguments cache
            mbd.preparedConstructorArguments = this.preparedArguments;
        } else {
            // If the parameters do not need to be resolved, put the arguments into the resolvedConstructorArguments cache
            mbd.resolvedConstructorArguments = this.arguments;
        }
    }
}

Put the parsed constructors and parameters into the cache, and check these caches in the first code block 6.

summary

This article introduces an important content of creating bean instance: creating a new bean instance. The rest of creating bean instances: filling properties, bean instance initialization and so on will be introduced in the next article.

Keywords: Spring

Added by exeterdad on Wed, 09 Feb 2022 09:49:53 +0200