SoFunction
Updated on 2025-04-25

Detailed explanation of the use cases of @Autowired, @Resource, @Inject annotation implementation principle in Spring

Use Cases

Prerequisites:Now there is oneVehicleInterface, it has two implementation classesBusandCar, there is another category nowVehicleServiceNeed to inject oneVehicleType of bean:

public interface Vehicle {}
@Component
public class Car implements Vehicle {}
@Component 
public class Bus implements Vehicle {}

use@AutowiredAnnotation injection Bean:

@AutowiredAnnotations can be combined with@QualifierUse annotations together to restrict beans with specific names injected if there are multiple beans that meet the criteria:

@Component
public class VehicleService {
    @Autowired
    @Qualifier("car") //Suppose here is the bean with the bean name car    private Vehicle vehicle;
}

use@InjectAnnotation injection Bean:

@InjectAnnotations can be combined with@Qualifieror@NamedUse annotations together to restrict beans with specific names injected if there are multiple beans that meet the criteria:

@Component
public class VehicleService {
    @Inject
    @Qualifier("car") //Suppose here is the bean with the bean name car    private Vehicle vehicle;
    @Inject
    @Named("bus") //Suppose here is the bean with the bean name bus that wants to inject    private Vehicle anotherVehicle;
}

use@ResourceAnnotation injection Bean:

@Component
public class VehicleService {
    @Resource(name = "car")
    private Vehicle vehicle;
}

Although the above three usage methods can all realize the requirements of injecting beans, what are the differences between them in the underlying implementation?

Annotation system

Several sets of annotations are defined in the Java EE and Spring systems:

JSR 250:Defined@PostConstruct@PreDestroy@ResourceAnnotation, of which@ResourceNoteBy default, injection is by name

JSR 330:Defined@Inject@Qualifier@NamedAnnotation, of which@InjectNoteBy default, injection is performed by type, can be matched@Qualifieror@NamedAnnotation implementation is injected according to name.

Spring:Defined@Autowired@QualifierAnnotation, of which@AutowiredNoteBy default, injection is performed by type, can be matched@QualifierAnnotation implementation is injected according to name.

The annotation currently defined by JSR 250 belongs to-api, and the annotation defined by JSR 330 belongs to-api

Implementation principle

The location where the InstantiationAwareBeanPostProcessor method call is triggered:

Provided in SpringInstantiationAwareBeanPostProcessorInterface, it has apostProcessProperties()Responsible for processing the properties of the bean.

Implementation classes are provided in SpringCommonAnnotationBeanPostProcessorResponsible for handling@ResourceAnnotation; implementation class is providedAutowiredAnnotationBeanPostProcessorResponsible for handling@AutowiredAnnotations and@InjectAnnotation.

InstantiationAwareBeanPostProcessorofpostProcessProperties()The method is inAbstractAutowireCapableBeanFactoryIndoCreateBean()The call triggered in the method that creates a bean. The main implementation logic in this method isInstantiate Bean -> Fill in Bean properties -> Initialize Bean.The code is as follows:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, 
	@Nullable Object[] args) throws BeanCreationException {
	BeanWrapper instanceWrapper = null;
	if (()) {
		instanceWrapper = (beanName);
	}
	if (instanceWrapper == null) {
        //Instantiate the Bean object		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	Object bean = ();
	boolean earlySingletonExposure = (() 
		&&  
		&& isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		addSingletonFactory(beanName, 
			() -> getEarlyBeanReference(beanName, mbd, bean));
	}
	Object exposedObject = bean;
	try {
        //Fill in Bean properties		populateBean(beanName, mbd, instanceWrapper);
		//Initialize Bean		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
}

Methods to fill Bean propertiespopulateBean()Implemented the rightpostProcessProperties()Method calls,In this method, the fields that need to be injected for annotation modification are assigned, that is, automatic injection.The code is as follows:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {  
    //Omit some code    PropertyValues pvs = (() ? () : null);  
    if (hasInstantiationAwareBeanPostProcessors()) {  
       if (pvs == null) {  
          pvs = ();  
       }  
       // Here we get all the implementation classes of InstantiationAwareBeanPostProcessor interfaces       for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {  
		  //Calling the postProcessProperties() method          PropertyValues pvsToUse = (pvs, 
	          (), beanName);  
          if (pvsToUse == null) {  
             return;  
          }  
          pvs = pvsToUse;  
       }  
    }  
}

InstantiationAwareBeanPostProcessor registration time:

now thatInstantiationAwareBeanPostProcessorIt is responsible for handling the automatic injection of the properties of the bean, so it must have been initialized before the business bean is created, so that its instance method can be called when the business bean is created. Its initialization is the base class in the Spring contextAbstractApplicationContextofrefresh()Completed in the method. The code is as follows:

public void refresh() throws BeansException, IllegalStateException {
    //Omit other codes	//The InstantiationAwareBeanPostProcessor is registered here	registerBeanPostProcessors(beanFactory);
    //Omit other codes	//Create all singleton beans here	finishBeanFactoryInitialization(beanFactory);
	finishRefresh();
}

And inregisterBeanPostProcessors()The method is called againPostProcessorRegistrationDelegateofregisterBeanPostProcessors()Method to complete the registration. The code is as follows:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    (beanFactory, this);
}

existPostProcessorRegistrationDelegateofregisterBeanPostProcessors()Methods truly implement registration logic. The code is as follows:

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, 
    AbstractApplicationContext applicationContext) {
    //Get all bean names that implement the BeanPostProcessor interface    //InstantiationAwareBeanPostProcessor interface inherits BeanPostProcessor interface    String[] postProcessorNames = (, true, false);
    //Transf the Bean name and call the() method to trigger the creation of the BeanPostProcessor Bean    //Then it is divided into three categories based on whether the PriorityOrdered interface, Ordered interface and others are implemented.    //Register BeanPostProcessor instances of these three categories respectively    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if ((ppName, )) {
            //Calling the() method here to trigger the creation of the BeanPostProcessor Bean            BeanPostProcessor pp = (ppName, );
            (pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                (pp);
            }
        }
        else if ((ppName, )) {
            (ppName);
        }
        else {
            (ppName);
        }
    }
    //First register the BeanPostProcessor that implements the PriorityOrdered interface    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    //Then trigger the creation and registration of the BeanPostProcessor Bean that implements the Ordered interface    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(());
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = (ppName, );
        (pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            (pp);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
    // Finally, the creation and registration of other BeanPostProcessor Beans are triggered.    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(());
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = (ppName, );
        (pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            (pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
}

CommonAnnotationBeanPostProcessor implementation logic (taking the modified field as an example)

First of all,CommonAnnotationBeanPostProcessorThe static initialization block initializes the annotation it wants to process. The code is as follows:

static {
    //This is to adapt to different versions of @Resource annotation under different package paths    jakartaResourceType = loadAnnotationType("");
    if (jakartaResourceType != null) {
        (jakartaResourceType);
    }
    //This is to adapt to different versions of @Resource annotation under different package paths    javaxResourceType = loadAnnotationType("");
    if (javaxResourceType != null) {
        (javaxResourceType);
    }
}

In itspostProcessProperties()The main implementation logic in the method is to find@ResourceAnnotation modified fields -> Assign values ​​to fields through reflection. The code is as follows:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // Find the @Resource annotation modified field    InjectionMetadata metadata = findResourceMetadata(beanName, (), pvs);
    try {
        // Assign a value to the field        (bean, beanName, pvs);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    }
    return pvs;
}

try to find@ResourceThe fields modified by the annotation are infindResourceMetadata()Implemented in the method, in which the method is called againbuildResourceMetadata()To perform actual search, in this method, traverse the field through reflection to see if it has@ResourceAnnotation modification, if so, package it as oneResourceElementPut the object into the list. Finally, construct a based on the listInjectionMetadataObject returns. The code is as follows:

private InjectionMetadata findResourceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    String cacheKey = ((beanName) ? beanName : ());
    InjectionMetadata metadata = (cacheKey);
    if ((metadata, clazz)) {
        synchronized () {
            metadata = (cacheKey);
            if ((metadata, clazz)) {
                if (metadata != null) {
                    (pvs);
                }
                //Call the buildResourceMetadata() method here                metadata = buildResourceMetadata(clazz);
                (cacheKey, metadata);
            }
        }
    }
    return metadata;
}
private InjectionMetadata buildResourceMetadata(Class<?> clazz) {
    List<> elements = new ArrayList<>();
    Class<?> targetClass = clazz;
    //Omit some code    do {
        final List<> currElements = new ArrayList<>();
        // Here we will traverse each field to see if the field has @Resource annotation modification, add it to the list        (targetClass, field -> {
           //Omit some code           if (jakartaResourceType != null && (jakartaResourceType)) {
                if ((())) {
                    throw new IllegalStateException("@Resource annotation is not supported on static fields");
                }
                if (!(().getName())) {
                    (new ResourceElement(field, field, null));
                }
            }
            else if (javaxResourceType != null && (javaxResourceType)) {
                if ((())) {
                    throw new IllegalStateException("@Resource annotation is not supported on static fields");
                }
                if (!(().getName())) {
                    (new LegacyResourceElement(field, field, null));
                }
            }
        });
        (0, currElements);
        targetClass = ();
    }
    while (targetClass != null && targetClass != );
    return (elements, clazz);
}

The actual operation to trigger the assignment isInjectionMetadataofinject()Implemented in the method will be called in a loop in its method.InjectedElementofinject()method. The code is as follows:

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = ;
    Collection<InjectedElement> elementsToIterate =
            (checkedElements != null ? checkedElements : );
    if (!()) {
        for (InjectedElement element : elementsToIterate) {
            (target, beanName, pvs);
        }
    }
}

existInjectedElementofinject()The method is used to assign the found bean to the field through reflection. The code is as follows:

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
	throws Throwable {
    if (!shouldInject(pvs)) {
        return;
    }
    if () {
        Field field = (Field) ;
        (field);
        //The value is set by reflection here. The value set is the Bean obtained according to the Bean name        (target, getResourceToInject(target, requestingBeanName));
    } else {
        //Omit other codes    }
}

existResourceElementofgetResourceToInject()The search logic is implemented in the method: ifBeanFactoryThe beans corresponding to the name of this bean are directly searched according to the name, otherwise they will match according to the type. This is what is commonly said@ResourceThe default annotation is to match according to the name. If the name cannot match, it will be matched according to the type. The code is as follows:

protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
    throws NoSuchBeanDefinitionException {
    //Omit the code    // Regular resource autowiring
    if ( == null) {
        throw new NoSuchBeanDefinitionException(,
                "No resource factory configured - specify the 'resourceFactory' property");
    }
    return autowireResource(, element, requestingBeanName);
}
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
	throws NoSuchBeanDefinitionException {
    Object resource;
    Set&lt;String&gt; autowiredBeanNames;
    String name = ;
    if (factory instanceof AutowireCapableBeanFactory autowireCapableBeanFactory) {
        //If the bean cannot be found according to the bean name and the first branch is allowed to match according to the type        if ( &amp;&amp;  &amp;&amp; !(name)) {
            autowiredBeanNames = new LinkedHashSet&lt;&gt;();
            resource = (
                    (), requestingBeanName, autowiredBeanNames, null);
            if (resource == null) {
                throw new NoSuchBeanDefinitionException((), "No resolvable resource object");
            }
        } else { //If you find a bean based on the name, you will directly obtain the bean based on the name            resource = (name, ());
            autowiredBeanNames = (name);
        }
    } else {
        //Omit the code    }
    //Omit the code    return resource;
}

The logic of type matching isDefaultListableBeanFactoryofdoResolveDependency()Implemented in the method,In this method, all beans of the current type will be found according to the type, and then a map is constructed. The key is the name of the bean and the value is the corresponding bean object. If the number of beans found is greater than 1, the return that best meets the criteria will be selected (the basis for selection will be discussed later). If it is equal to 1, the bean will be directly returned.. The code is as follows:

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
	@Nullable Set&lt;String&gt; autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
	InjectionPoint previousInjectionPoint = (descriptor);
	try {
		//Omit the code		// Here all beans are found according to the type, and then the name of the bean is used as the key and the bean is used as the Value		Map&lt;String, Object&gt; matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (()) {
			// Step 4c (fallback): custom Collection / Map declarations for collecting multiple beans
			multipleBeans = resolveMultipleBeansFallback(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}
			// Raise exception if nothing found for required injection point
			if (isRequired(descriptor)) {
				raiseNoMatchingBeanFound(type, (), descriptor);
			}
			return null;
		}
		String autowiredBeanName;
		Object instanceCandidate;
		//If you find multiple beans according to the type, you need to select a suitable bean to return		if (() &gt; 1) {
			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
			if (autowiredBeanName == null) {
				if (isRequired(descriptor) || !indicatesArrayCollectionOrMap(type)) {
					// Raise exception if no clear match found for required injection point
					return ((), 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;
				}
			}
			instanceCandidate = (autowiredBeanName);
		} else {
			//If there is only one bean, return this bean directly			&lt;String, Object&gt; entry = ().iterator().next();
			autowiredBeanName = ();
			instanceCandidate = ();
		}
		// Step 6: validate single result
		if (autowiredBeanNames != null) {
			(autowiredBeanName);
		}
		if (instanceCandidate instanceof Class) {
			instanceCandidate = (autowiredBeanName, type, this);
		}
		return resolveInstance(instanceCandidate, descriptor, type, autowiredBeanName);
	}
	finally {
		(previousInjectionPoint);
	}
}

AutowiredAnnotationBeanPostProcessor implementation logic (taking the modified field as an example)

First, the annotations that need to be processed in the constructor include@Autowiredand@InjectAnnotation. The code is as follows:

public AutowiredAnnotationBeanPostProcessor() {
    //Add @Autowired annotation to be processed    ();
    ();
    ClassLoader classLoader = ();
    try {
        //This is to adapt to different versions of @Inject annotation under different package paths        ((Class&lt;? extends Annotation&gt;)
                ("", classLoader));
    } catch (ClassNotFoundException ex) {
        //  API not available - simply skip.
    }
    try {
        //This is to adapt to different versions of @Inject annotation under different package paths        ((Class&lt;? extends Annotation&gt;)
                ("", classLoader));
    } catch (ClassNotFoundException ex) {
        //  API not available - simply skip.
    }
}

In itspostProcessProperties()The main implementation logic in the method is to find@Autowiredor@InjectAnnotation modified fields -> Assign values ​​to fields through reflection. The code is as follows:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, (), pvs);
    try {
        (bean, beanName, pvs);
    }
    catch (BeanCreationException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}

try to find@Autowiredor@InjectThe fields modified by the annotation are infindAutowiringMetadata()Implemented in the method, in which the method is called againbuildAutowiringMetadata()To perform actual search, in this method, traverse the field through reflection to see if it has@Autowiredor@InjectAnnotation modification, if so, wrap it into oneAutowiredFieldElementPut the object into the list. Finally, construct a based on the listInjectionMetadataObject returns. The code is as follows:

private InjectionMetadata findAutowiringMetadata(String beanName, Class&lt;?&gt; clazz, @Nullable PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    String cacheKey = ((beanName) ? beanName : ());
    // Quick check on the concurrent map first, with minimal locking.
    InjectionMetadata metadata = (cacheKey);
    if ((metadata, clazz)) {
        synchronized () {
            metadata = (cacheKey);
            if ((metadata, clazz)) {
                if (metadata != null) {
                    (pvs);
                }
                metadata = buildAutowiringMetadata(clazz);
                (cacheKey, metadata);
            }
        }
    }
    return metadata;
}
private InjectionMetadata buildAutowiringMetadata(Class&lt;?&gt; clazz) {
    if (!(clazz, )) {
        return ;
    }
    final List&lt;&gt; elements = new ArrayList&lt;&gt;();
    Class&lt;?&gt; targetClass = clazz;
    do {
        final List&lt;&gt; fieldElements = new ArrayList&lt;&gt;();
        (targetClass, field -&gt; {
            //I found here whether there are @Autowired or @Inject annotation modifications            MergedAnnotation&lt;?&gt; ann = findAutowiredAnnotation(field);
            if (ann != null) {
                if ((())) {
                    return;
                }
                boolean required = determineRequiredStatus(ann);
                (new AutowiredFieldElement(field, required));
            }
        });
    }
}

The actual operation to trigger the assignment isInjectionMetadataofinject()Implemented in the method will be called in a loop in its method.AutowiredFieldElementofinject()method. The code is as follows:

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = ;
    Collection<InjectedElement> elementsToIterate =
            (checkedElements != null ? checkedElements : );
    if (!()) {
        for (InjectedElement element : elementsToIterate) {
            (target, beanName, pvs);
        }
    }
}

existInjectedElementofinject()The method is used to assign the found bean to the field through reflection. The code is as follows:

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) ;
    Object value;
    if () {
        //Omit the code    } else {
        //Find the corresponding bean        value = resolveFieldValue(field, bean, beanName);
    }
    if (value != null) {
        (field);
        //Assign value through reflection        (bean, value);
    }
}
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
    DependencyDescriptor desc = new DependencyDescriptor(field, );
    (());
    Set&lt;String&gt; autowiredBeanNames = new LinkedHashSet&lt;&gt;(2);
    TypeConverter typeConverter = ();
    Object value;
    try {
        //Calling the resolveDependency() method of beanFactory        value = (desc, beanName, autowiredBeanNames, typeConverter);
    } catch (BeansException ex) {
        throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
    }
    return value;
}

Then it will be calledDefaultListableBeanFactoryofdoResolveDependency()Method, and above@ResourceAnnotation The call that cannot be found based on the name The bean needs to match according to the type is a method, but it will have one more branch.In this branch, determine whether the bean corresponding to the bean name exists. If it exists, it will be returned directly. If it does not exist, it will be matched according to the type. In fact, it will be matched according to the name first. If the name cannot match, the logic of type matching will be followed before going.. The code is as follows:

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
	@Nullable Set&lt;String&gt; autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
	InjectionPoint previousInjectionPoint = (descriptor);
	try {
		//Omit the code        //If it is @Autowired annotation or @Inject annotation, you will first go to the following branch        //In this branch, you will also first determine whether the bean corresponding to the bean name exists. If it exists        //Then directly get the return, and if it does not exist, it will match according to the type        if (()) {
            String dependencyName = ();
            if (dependencyName == null || !containsBean(dependencyName)) {
                String suggestedName = getAutowireCandidateResolver().getSuggestedName(descriptor);
                dependencyName = (suggestedName != null &amp;&amp; containsBean(suggestedName) ? suggestedName : null);
            }
            if (dependencyName != null) {
                dependencyName = canonicalName(dependencyName);  // dependency name can be alias of target name
                if (isTypeMatch(dependencyName, type) &amp;&amp; isAutowireCandidate(dependencyName, descriptor) &amp;&amp;
                        !isFallback(dependencyName) &amp;&amp; !hasPrimaryConflict(dependencyName, type) &amp;&amp;
                        !isSelfReference(beanName, dependencyName)) {
                    if (autowiredBeanNames != null) {
                        (dependencyName);
                    }
                    Object dependencyBean = getBean(dependencyName);
                    return resolveInstance(dependencyBean, descriptor, type, dependencyName);
                }
            }
        }
		// Here all beans are found according to the type, and then the name of the bean is used as the key and the bean is used as the Value		Map&lt;String, Object&gt; matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (()) {
			// Step 4c (fallback): custom Collection / Map declarations for collecting multiple beans
			multipleBeans = resolveMultipleBeansFallback(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}
			// Raise exception if nothing found for required injection point
			if (isRequired(descriptor)) {
				raiseNoMatchingBeanFound(type, (), descriptor);
			}
			return null;
		}
		String autowiredBeanName;
		Object instanceCandidate;
		//If you find multiple beans according to the type, you need to select a suitable bean to return		if (() &gt; 1) {
			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
			if (autowiredBeanName == null) {
				if (isRequired(descriptor) || !indicatesArrayCollectionOrMap(type)) {
					// Raise exception if no clear match found for required injection point
					return ((), 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;
				}
			}
			instanceCandidate = (autowiredBeanName);
		} else {
			//If there is only one bean, return this bean directly			&lt;String, Object&gt; entry = ().iterator().next();
			autowiredBeanName = ();
			instanceCandidate = ();
		}
		// Step 6: validate single result
		if (autowiredBeanNames != null) {
			(autowiredBeanName);
		}
		if (instanceCandidate instanceof Class) {
			instanceCandidate = (autowiredBeanName, type, this);
		}
		return resolveInstance(instanceCandidate, descriptor, type, autowiredBeanName);
	}
	finally {
		(previousInjectionPoint);
	}
}

The principle of returning a bean when there are multiple types matching beans

When multiple beans are found according to type, one bean needs to be returned according to some rules. Common ones can be passed@QualiferQualified name or through@PrimaryTo indicate priority injection. existDefaultListableBeanFactorofdetermineAutowireCandidate()The method implements these logics:

First iterate through all beans that match the type found, and then see if there are@PrimaryAnnotation modification, if there is any, the bean is returned first;

Otherwise, try again to see if there is a matching bean based on the field name, and return if so;

Otherwise try to get@QualifierName of the annotation definition (for@NamedAnnotation: it also has@QualiferAnnotation modification), then see if there is a bean with a name matching, and if so, return it;

Otherwise, traverse the bean to see if there is@PriorityAnnotation modification. If there is one, find the highest priority bean to return. The smaller the value, the higher the priority;

Otherwise, lookresolvableDependenciesWhether there is a corresponding instance to register, and if so, it will return. Its usage scenario is generally that the user's own new object can be registered here, and then it can be injected into a Spring-managed bean. The code is as follows:

protected String determineAutowireCandidate(Map&lt;String, Object&gt; candidates, DependencyDescriptor descriptor) {
    Class&lt;?&gt; requiredType = ();
    //First process @Primary annotation, if a bean has @Primary annotation modification, it will be returned first    String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
    if (primaryCandidate != null) {
        return primaryCandidate;
    }
    // Otherwise, match again according to the name of the field to see if there is a bean with the same name as the field in the bean found. If so, return it first.    String dependencyName = ();
    if (dependencyName != null) {
        for (String beanName : ()) {
            if (matchesBeanName(beanName, dependencyName)) {
                return beanName;
            }
        }
    }
    // Otherwise, try to get the name defined by the @Qualifier annotation, see if there is a bean with the same name as the bean in the bean you are looking for. If so, return it first    String suggestedName = getAutowireCandidateResolver().getSuggestedName(descriptor);
    if (suggestedName != null) {
        for (String beanName : ()) {
            if (matchesBeanName(beanName, suggestedName)) {
                return beanName;
            }
        }
    }
    // Otherwise, see if the bean found is modified with @Priority annotation. If so, take the highest priority and return the lowest value, which is the lowest value.    String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
    if (priorityCandidate != null) {
        return priorityCandidate;
    }
    // Otherwise, if there is a match in the custom registered object that is not Spring management lifecycle, you can put it in resolvableDependencies    //Some objects, these objects are not created by Spring but are created by the user themselves and need to be injected into a Spring bean    for (&lt;String, Object&gt; entry : ()) {
        String candidateName = ();
        Object beanInstance = ();
        if (beanInstance != null &amp;&amp; (beanInstance)) {
            return candidateName;
        }
    }
    return null;
}

@NamedUsed in the annotation definition@QualiferAnnotation modification. The code is as follows:

@Qualifier // @Qualifer annotation is used here@Documented
@Retention(RUNTIME)
public @interface Named {
    String value() default "";
}

This is the end of this article about @Autowired, @Resource, @Inject annotation implementation principles in Spring. For more related contents of @Autowired, @Resource, @Inject annotation implementation principles in Spring, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!