• instantiateBean(beanName, mbd); Instantiate the object using the default constructor.
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
	try {
		Object beanInstance;
		final BeanFactory parent = this;
		if(System.getSecurityManager() ! =null) {
			beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
					getInstantiationStrategy().instantiate(mbd, beanName, parent),
					getAccessControlContext());
		}
		else {
			/ / getInstantiationStrategy class instantiation strategy ()
			// The default is to get a reflected instantiation policy
			beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
		}
		BeanWrapper bw = new BeanWrapperImpl(beanInstance);
		initBeanWrapper(bw);
		return bw;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
	}
}

# SimpleInstantiationStrategy
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
	// Don't override the class with CGLIB if no overrides.
	// Check whether the bean configuration is configured with lookup-method or replace-method
	// If configured, you need to use CGLIB to build the bean object
	if(! bd.hasMethodOverrides()) { Constructor<? > constructorToUse;synchronized(bd.constructorArgumentLock) { constructorToUse = (Constructor<? >) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {
				finalClass<? > clazz = bd.getBeanClass();if (clazz.isInterface()) {
					throw new BeanInstantiationException(clazz, "Specified class is an interface");
				}
				try {
					if(System.getSecurityManager() ! =null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<? >>) clazz::getDeclaredConstructor); }else {
						// Get the default constructor with no parameters
						//constructorToUse: indicates which constructorToUse Spring uses to instantiate an object
						constructorToUse =	clazz.getDeclaredConstructor();
					}
					/ / record resolvedConstructorOrFactoryMethod is the default constructor
					bd.resolvedConstructorOrFactoryMethod = constructorToUse;
				}
				catch (Throwable ex) {
					throw new BeanInstantiationException(clazz, "No default constructor found", ex); }}}// Invoke the reflection technique to instantiate the object
		return BeanUtils.instantiateClass(constructorToUse);
	}
	else {
		// Must generate CGLIB subclass.
		returninstantiateWithMethodInjection(bd, beanName, owner); }}public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
	Assert.notNull(ctor, "Constructor must not be null");
	try {
		// Set the constructor to accessible
		ReflectionUtils.makeAccessible(ctor);
		// Reflect to create object tor.newinstance (args)
		return (KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
				KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
	}
	catch (InstantiationException ex) {
		throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
	}
	catch (IllegalAccessException ex) {
		throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
	}
	catch (IllegalArgumentException ex) {
		throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
	}
	catch (InvocationTargetException ex) {
		throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException()); }}Copy the code
  • autowireConstructor(beanName, mbd, ctors, args); Instantiate an object using a constructor that takes a parameter.
protected BeanWrapper autowireConstructor(
			String beanName, RootBeanDefinition mbd, @NullableConstructor<? >[] ctors,@Nullable Object[] explicitArgs) {
	return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
			@NullableConstructor<? >[] chosenCtors,@Nullable Object[] explicitArgs) {
	// Strength a BeanWrapperImpl object is easy to understand
	BeanWrapperImpl BeanWrapperImpl BeanWrapperImpl
	BeanWrapper is an interface
	BeanWrapperImpl bw = new BeanWrapperImpl();
	this.beanFactory.initBeanWrapper(bw);

	// Decide which constructor to use to instantiate the objectConstructor<? > constructorToUse =null;

	// The value of the constructor. Note that it is not a parameter
	// We all know that constructors instantiate an object by reflection
	// When calling reflection to instantiate an object, you need a specific value
	// This variable is used to record these values
	ArgsHolderToUse is a data structure
	ArgumentsHolder argsHolderToUse = null;

	//argsToUse[] is the real value
	Object[] argsToUse = null;

	// Determine the list of parameter values
	ArgsToUse can be set in two ways
	// The first is set by beanDefinition
	// The second is set through XML
	if(explicitArgs ! =null) {
		argsToUse = explicitArgs;
	}
	else {
		Object[] argsToResolve = null;
		synchronized (mbd.constructorArgumentLock) {
			// Get the parsed constructor
			// Usually not, because the constructor usually provides one
			// Unless there are more than one. Then there are constructors that have been parsedconstructorToUse = (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); }}if (constructorToUse == null) {
		// If there is no parser constructor
		// We need to parse the constructor
		// Determine if the constructor is null and if the constructor is automatically injected
		booleanautowiring = (chosenCtors ! =null ||
				mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
		ConstructorArgumentValues resolvedValues = null;

		// Define the minimum number of parameters minNrOfArgs
		// If you give specific values to the constructor's argument list
		// Then these values are the number of constructor parameters
		int minNrOfArgs;
		if(explicitArgs ! =null) {
			// If the number of arguments passed is not null, then the "minimum number of arguments" is the number of arguments passed.
			minNrOfArgs = explicitArgs.length;
		}
		else {
			/ / mybatis: MBD. GetConstructorArgumentValues () addGenericArgumentValue (" com. Index. Dao ");
			// Instantiate an object that holds the constructor parameter values
			// It mainly stores the parameter values and the table corresponding to the parameter values
			ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
			resolvedValues = new ConstructorArgumentValues();
			/** * determine the number of constructor parameters, assuming the following configuration:  * 
      
        * 
        * 
        * 
        * 
       * * Then the "minimum number of arguments" for your constructor is determined by * * minNrOfArgs = 3 */
			minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
		}

		// Take specified constructors, if any.Constructor<? >[] candidates = chosenCtors;if (candidates == null) { Class<? > beanClass = mbd.getBeanClass();try {
				candidates = (mbd.isNonPublicAccessAllowed() ?
						beanClass.getDeclaredConstructors() : beanClass.getConstructors());
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Resolution of declared constructors on bean Class [" + beanClass.getName() +
						"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex); }}// How to sort?
		Public -- protected -- private public -- protected -- private
		//2. Order the constructor from most to least by the number of parameters
		/** * Public Luban(Object o1, Object O2, Object O3) * 2. Public Luban(Object o1, Object O2, Object O3) * 3. Object o2) * 3. public Luban(Object o1) * 4. protected Luban(Integer i, Object o1, Object o2, Object o3) * 5. protected Luban(Integer i, Object o1, Object o2) * 6. protected Luban(Integer i, Object o1) */
		AutowireUtils.sortConstructors(candidates);
		// Define a difference variable. This variable has a lot of weight and is commented after it
		intminTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<? >> ambiguousConstructors =null;  // Record the constructor of the exception (constructor difference value is the same, spring does not know how to choose)
		LinkedList<UnsatisfiedDependencyException> causes = null;

		// Loop through all constructors
		for(Constructor<? > candidate : candidates) { Class<? >[] paramTypes = candidate.getParameterTypes();/** * constructorToUse * constructorToUse * constructorToUse * constructorToUse * constructorToUse * constructorToUse * constructorToUse = null which makes sense * we've already said that first of all constructorToUse is primarily used to hold a constructor that has already been parsed and used * it only continues if it equals null, Because the following constructor * will be assigned to the variable if it is resolved (as commented below). If this variable is not null, no further parsing is required, indicating that Spring has * found an appropriate constructor. * argsToUse = [1,"llsydn",obj] * then match back to the above constructor 1 and 5 * Since constructor 1 has higher access, all options are 1, although 5 looks like a better match * but if we look at 2, the number of arguments is not right so we just ignore * */
			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;
			}
			// If the length of the argument types traversed by the current constructor is not equal to the minimum argument format: Prove that the object cannot be instantiated with the constructor
			if (paramTypes.length < minNrOfArgs) {
				continue;
			}

			ArgumentsHolder argsHolder;
			if(resolvedValues ! =null) {
				try {
					// Determine whether the ConstructorProperties annotation is used, and if so, take out the value
					// Write code to test this
					//@ConstructorProperties(value = {"xxx", "111"})
					String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
					if (paramNames == null) {
						ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
						if(pnd ! =null) {
							// Get a list of constructor parameter names
							/** * Suppose you have (String llsydn, Object zilu) * then paramNames=[llsydn, Object zilu] */paramNames = pnd.getParameterNames(candidate); }}// Get a list of constructor parameter values
					/** * This method is complicated * because Spring can only supply string arguments * so the conversion is required ** The value contained in the argsHolder is the converted ** for example, if you set "order" in the XML configuration file, which is a string, to be converted to the order object */
					argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
							getUserDeclaredConstructor(candidate), autowiring);
				}
				catch (UnsatisfiedDependencyException ex) {
					if (logger.isTraceEnabled()) {
						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.
				if(paramTypes.length ! = explicitArgs.length) {continue;
				}
				argsHolder = new ArgumentsHolder(explicitArgs);
			}

			/** * typeDiffWeight * The difference between argsholde. arguments and paramTypes * the difference between each parameter value type and the type of the constructor parameter list directly * This difference is used to measure or determine an appropriate constructor * * Note that constructorToUse=candidate * * the first loop will definitely typeDiffWeight < minTypeDiffWeight, Because the value of minTypeDiffWeight is very large * and then every time the loop is going to assign typeDiffWeight to minTypeDiffWeight (minTypeDiffWeight = typeDiffWeight) * else if (constructorToUse ! = null && typeDiffWeight == minTypeDiffWeight) * The first time the loop definitely doesn't go into this * The second time if it goes into this branch what does it mean? * means that there are two constructors that meet our requirements? So spring has lost (spring is often lost) * Spring lost how to do? * ambiguousConstructors.add(candidate); * As the name suggests... * ambiguousConstructors=null important? If the ambiguousConstructors always exist, Spring will remove exception outside the loop. !!!! * /
			int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
					argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
			// Choose this constructor if it represents the closest match.
			if (typeDiffWeight < minTypeDiffWeight) {
				// The first time 100% will enter here; When a smaller difference is found, the exception is cleared.
				constructorToUse = candidate;
				argsHolderToUse = argsHolder;
				argsToUse = argsHolder.arguments;
				minTypeDiffWeight = typeDiffWeight;
				// Empty the exception constructor
				ambiguousConstructors = null;
			}
			else if(constructorToUse ! =null && typeDiffWeight == minTypeDiffWeight) {
				// ambiguousConstructors are commonly used for constructors, but spring does not know how to select them. It first records them in ambiguousConstructors.
				if (ambiguousConstructors == null) {
					ambiguousConstructors = newLinkedHashSet<>(); ambiguousConstructors.add(constructorToUse); } ambiguousConstructors.add(candidate); }}// The loop ends
		// There is no suitable construction method
		if (constructorToUse == null) {
			if(causes ! =null) {
				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)");
		}

		// If ambiguousConstructors still exist, what is the exception? Why is there a direct exception in the above method?
		// This is explained in the comments above
		else if(ambiguousConstructors ! =null && !mbd.isLenientConstructorResolution()) {
			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) {
			/ * * cache information, such as: * 1. Parsed the constructor object resolvedConstructorOrFactoryMethod * 2. Whether the constructor argument list parsed constructorArgumentsResolved * 3. Parameter value list resolvedConstructorArguments or preparedConstructorArguments * this information is available in other places, for quick judgment * /argsHolderToUse.storeCache(mbd, constructorToUse); }}try {
		/* * Use reflection to create instance lookup-method to enhance bean instances with CGLIB */
		final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
		Object beanInstance;

		if(System.getSecurityManager() ! =null) {
			finalConstructor<? > ctorToUse = constructorToUse;final Object[] argumentsToUse = argsToUse;
			beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
					strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse),
					beanFactory.getAccessControlContext());
		}
		else {
			// Finally: instantiate the object by finding the constructorToUse method
			beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
		}
		bw.setBeanInstance(beanInstance);
		return bw;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"Bean instantiation via constructor failed", ex); }}Copy the code

AutowireConstructor instantiates an object using a special constructor. Determine which constructor to instantiate the object with: constructorToUse, and those parameters: argsToUse 2. First determine the minimum number of arguments to the constructor: minNrOfArgs. 3. Sort all constructors by their level of access (public–protected–private) and number of arguments (from most to least) 4. Iterate over all constructors to determine whether the constructor conforms to 5 according to the “minimum number of parameters” minNrOfArgs. Calculate the “typeDiffWeight” of the constructor, find the smallest difference, and spring instantiates the object with this constructor. 6. If Spring finds multiple constructors with the same difference and the smallest number of parameters, record them in ambiguousConstructors. 7. If the ambiguousConstructors always exist, Spring will remove exception 8 outside of the loop. If the ambiguousConstructors is NULL, Spring caches the found constructorToUse method 9. Finally, we instantiate the object by finding the constructorToUse method.

1.instanceWrapper = createBeanInstance(beanName, mbd, args);

This is where the method of instantiating an object using a constructor is resolved. To create an object, perform the following step

2.addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

This is very important because you basically store new objects in the singletonFactories object. It is mainly used to solve circular dependencies.

3.populateBean(beanName, mbd, instanceWrapper); But at this point, the object has not yet been assigned, so you need to call this method to assign the property

  • populateBean(beanName, mbd, instanceWrapper);
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	if (bw == null) {
		if (mbd.hasPropertyValues()) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
		}
		else {
			// Skip property population phase for null instance.
			return; }}// Whether attribute assignment is required
	boolean continueWithPropertyPopulation = true;

	/ / implementation InstantiationAwareBeanPostProcessor interface, can do not attribute assignment, returns an object
	if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation =false;
					break; }}}}if(! continueWithPropertyPopulation) {return;
	}

	/ / property values
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

	// Attribute automatic assembly model (NO)
	if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
		// Add property values based on autowire by name if applicable.
		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}
		// Add property values based on autowire by type if applicable.
		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
			autowireByType(beanName, mbd, bw, newPvs);
		}
		pvs = newPvs;
	}

	/ / do you need InstantiationAwareBeanPostProcessors processing
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	// Whether deep checking (circular reference) is required
	booleanneedsDepCheck = (mbd.getDependencyCheck() ! = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);if (hasInstAwareBpps || needsDepCheck) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		// Get all get and set methods
		PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		if (hasInstAwareBpps) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvs == null) {
						return; }}}}if(needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); }}if(pvs ! =null) { applyPropertyValues(beanName, mbd, bw, pvs); }}Copy the code

Attribute assignment is done here, mainly by calling two BeanPostProcessors for attribute assignment. 1. AutowiredAnnotationBeanPostProcessor (processing the @autowired annotation) 2. com monAnnotationBeanPostProcessor (@ Resource, @ PostConstruct and @ PreDestroy annotations)

  • AutowiredAnnotationBeanPostProcessor source code parsing
// @autowired implements property injection
@Override
public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

	// Find the properties and methods in the class annotated by @autowired
	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
		// Attribute injection
		metadata.inject(bean, beanName, pvs);
	}
	catch (BeanCreationException ex) {
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
	}
	return pvs;
}

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// Get the attributes to inject
	Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements ! =null ? checkedElements : this.injectedElements);
	if(! elementsToIterate.isEmpty()) {// Iterate over the injected properties one by one
		for (InjectedElement element : elementsToIterate) {
			if (logger.isDebugEnabled()) {
				logger.debug("Processing injected element of bean '" + beanName + "'." + element);
			}
			// Attribute injectionelement.inject(target, beanName, pvs); }}}@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	// Get the attribute to inject
	Field field = (Field) this.member;
	Object value;
	if (this.cached) {
		// If it is cached, take it from the cache
		value = resolvedCachedArgument(beanName, this.cachedFieldValue);
	}
	else {
		DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
		desc.setContainingClass(bean.getClass());
		Set<String> autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory ! =null."No BeanFactory available");
		TypeConverter typeConverter = beanFactory.getTypeConverter();
		try {
			// Convert this dependency from BeanFactory (important)
			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
		}
		synchronized (this) {
			if (!this.cached) {
				if(value ! =null || this.required) {
					this.cachedFieldValue = desc;
					registerDependentBeans(beanName, autowiredBeanNames);
					if (autowiredBeanNames.size() == 1) {
						String autowiredBeanName = autowiredBeanNames.iterator().next();

						// isTypeMatch is the same type of "autowiring beans" from earlySingletonObjects
						Field. Set (bean, value);
						if (beanFactory.containsBean(autowiredBeanName) &&
								beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
							this.cachedFieldValue = newShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); }}}else {
					this.cachedFieldValue = null;
				}
				this.cached = true; }}}if(value ! =null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); }}@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	// Determine the type of dependency
	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 Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
	}
	else {
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
			// Convert this dependency from the BeanFactory
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		returnresult; }}@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
	try {
		Object shortcut = descriptor.resolveShortcut(this);
		if(shortcut ! =null) {
			returnshortcut; } Class<? > type = descriptor.getDependencyType(); Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);if(value ! =null) {
			if (value instanceofString) { String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName ! =null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter ! =null ? typeConverter : getTypeConverter());
			return(descriptor.getField() ! =null ?
					converter.convertIfNecessary(value, type, descriptor.getField()) :
					converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
		}

		Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
		if(multipleBeans ! =null) {
			return multipleBeans;
		}

		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (matchingBeans.isEmpty()) {
			if (isRequired(descriptor)) {
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			return null;
		}

		String autowiredBeanName;
		Object instanceCandidate;

		if (matchingBeans.size() > 1) {
			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
			if (autowiredBeanName == null) {
				if(isRequired(descriptor) || ! indicatesMultipleBeans(type)) {return descriptor.resolveNotUnique(type, matchingBeans);
				}
				else {
					return null;
				}
			}
			instanceCandidate = matchingBeans.get(autowiredBeanName);
		}
		else {
			// We have exactly one match.
			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
			autowiredBeanName = entry.getKey();
			instanceCandidate = entry.getValue();
		}

		if(autowiredBeanNames ! =null) {
			autowiredBeanNames.add(autowiredBeanName);
		}
		if (instanceCandidate instanceof Class) {
			// Process the autolight attributes to perform the transformation. The @autowired important
			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); }}public Object resolveCandidate(String beanName, Class
        requiredType, BeanFactory beanFactory)
		throws BeansException {
	// The getBean method is called again
	return beanFactory.getBean(beanName);
}
Copy the code

For example, class A has an attribute of class B, and class B has an attribute of class A. So when the property is populated, it will appear when the A object is created, and then the B object will be automatically assembled, so spring will also create the B object. So at this point, you have a circular dependency. So how does Spring solve circular dependencies?

  • In the case of cyclic dependencies, Spring mainly uses three maps, one list, and the most important of these is singletonFactories
// At this point, the bean has been created, but has not yet been assembled
protected void addSingletonFactory(String beanName, ObjectFactory
        singletonFactory) {
	Assert.notNull(singletonFactory, "Singleton factory must not be null");
	synchronized (this.singletonObjects) {
		//singletonObjects are complete objects
		if (!this.singletonObjects.containsKey(beanName)) {
			// has been created by new, but the properties are not populated, mainly to resolve circular dependencies
			this.singletonFactories.put(beanName, singletonFactory);
			// has been written by new, but the attributes are not filled in, mainly as type validation
			this.earlySingletonObjects.remove(beanName);
			// Record this at registeredSingletons
			this.registeredSingletons.add(beanName); }}}// This method is called when the attribute assignment takes place, fetching the dependent beans from the singletonFactories for the attribute assignment
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	// Get the bean from the map and return it if it is not empty
	// An object provided by a programmer is usually empty
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null&& allowEarlyReference) { ObjectFactory<? > singletonFactory =this.singletonFactories.get(beanName);
				if(singletonFactory ! =null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName); }}}}return singletonObject;
}
Copy the code

This is the end of spring’s instantiation of beans. The following is a flowchart of the Spring instantiation process: