Spring 中@Autowired,@Resource,@Inject 注解实现原理

使用案例

前置条件: 现在有一个 Vehicle 接口,它有两个实现类 BusCar ,现在还有一个类 VehicleService 需要注入一个 Vehicle 类型的 Bean:

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

使用 @Autowired 注解注入 Bean

@Autowired 注解可以和 @Qualifier 注解一起使用,在有多个符合条件的 Bean 的情况下限制注入特定名称的 Bean:

@Component public class VehicleService {     @Autowired     @Qualifier("car") //假设这里是想要注入Bean名称为car的这个Bean     private Vehicle vehicle; } 

使用 @Inject 注解注入 Bean

@Inject 注解可以和 @Qualifier或者 @Named 注解一起使用,在有多个符合条件的 Bean 的情况下限制注入特定名称的 Bean:

@Component public class VehicleService {     @Inject     @Qualifier("car") //假设这里是想要注入Bean名称为car的这个Bean     private Vehicle vehicle;      @Inject     @Named("bus") //假设这里是想要注入Bean名称为bus的这个Bean     private Vehicle anotherVehicle; } 

使用 @Resource 注解注入 Bean:

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

虽然以上三种使用方法都能够实现注入 Bean 的需求,但是它们在底层实现上有什么区别呢?

注解体系

在 Java EE 和 Spring 体系中定义了几套注解:

JSR 250:定义了 @PostConstruct@PreDestroy@Resource 注解,其中 @Resource 注解默认是按照名称进行注入

JSR 330:定义了 @Inject@Qualifier, @Named 注解,其中 @Inject 注解默认是按照类型进行注入,可以搭配 @Qualifier 或者@Named 注解实现按照名称注入。

Spring:定义了 @Autowired@Qualifier注解,其中 @Autowired 注解默认是按照类型进行注入,可以搭配 @Qualifier 注解实现按照名称注入。

当前 JSR 250 定义的注解属于 jakarta.annotation-api,而 JSR 330 定义的注解属于 jakarta.inject-api

实现原理

InstantiationAwareBeanPostProcessor 方法调用触发的位置:

Spring 中提供了 InstantiationAwareBeanPostProcessor 接口,它有一个 postProcessProperties() 负责实现对 Bean 的属性进行处理。

Spring 中提供了实现类 CommonAnnotationBeanPostProcessor 负责处理 @Resource 注解;提供了实现类 AutowiredAnnotationBeanPostProcessor 负责处理 @Autowired 注解和 @Inject 注解。

InstantiationAwareBeanPostProcessorpostProcessProperties() 方法是在 AbstractAutowireCapableBeanFactory 中的 doCreateBean() 创建 Bean 的方法中触发调用的,在这个方法中的主要实现逻辑是实例化 Bean -> 填充 Bean 属性 -> 初始化 Bean。 代码如下:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd,  	@Nullable Object[] args) throws BeanCreationException { 	BeanWrapper instanceWrapper = null; 	if (mbd.isSingleton()) { 		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 	} 	if (instanceWrapper == null) {         //实例化Bean对象 		instanceWrapper = createBeanInstance(beanName, mbd, args); 	} 	Object bean = instanceWrapper.getWrappedInstance();  	boolean earlySingletonExposure = (mbd.isSingleton()  		&& this.allowCircularReferences  		&& isSingletonCurrentlyInCreation(beanName)); 	if (earlySingletonExposure) { 		addSingletonFactory(beanName,  			() -> getEarlyBeanReference(beanName, mbd, bean)); 	}  	Object exposedObject = bean; 	try {         //填充Bean属性 		populateBean(beanName, mbd, instanceWrapper); 		//初始化Bean 		exposedObject = initializeBean(beanName, exposedObject, mbd); 	} } 

在填充 Bean 属性的方法 populateBean() 中实现了对 postProcessProperties() 方法的调用,在该方法实现对注解修饰的需要注入的字段进行赋值,即自动注入。 代码如下:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {       //省略部分代码     PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);       if (hasInstantiationAwareBeanPostProcessors()) {          if (pvs == null) {             pvs = mbd.getPropertyValues();          }          //这里获取所有InstantiationAwareBeanPostProcessor接口的实现类        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {   		  //调用postProcessProperties()方法           PropertyValues pvsToUse = bp.postProcessProperties(pvs,  	          bw.getWrappedInstance(), beanName);             if (pvsToUse == null) {                return;             }             pvs = pvsToUse;          }       }   } 

InstantiationAwareBeanPostProcessor 注册的时机:

既然 InstantiationAwareBeanPostProcessor 是负责处理 Bean 的属性的自动注入的,那么它一定是在业务 Bean 创建之前就已经完成初始化了,这样在业务 Bean 创建的时候才能调用它的实例方法。它的初始化是在 Spring 上下文的基类 AbstractApplicationContextrefresh() 方法中完成的。代码如下:

public void refresh() throws BeansException, IllegalStateException {     //省略其它代码 	//这里注册了InstantiationAwareBeanPostProcessor 	registerBeanPostProcessors(beanFactory); 	     //省略其它代码      	//这里创建所有的单例Bean 	finishBeanFactoryInitialization(beanFactory);      	finishRefresh(); } 

而在 registerBeanPostProcessors() 方法中又调用了 PostProcessorRegistrationDelegateregisterBeanPostProcessors() 方法来完成注册的。代码如下:

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

PostProcessorRegistrationDelegateregisterBeanPostProcessors() 方法真正实现注册逻辑。代码如下:

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory,      AbstractApplicationContext applicationContext) {     //这里获取到所有实现了BeanPostProcessor接口的Bean名称     //InstantiationAwareBeanPostProcessor接口继承了BeanPostProcessor接口     String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);      //遍历Bean名称调用BeanFactory.getBean()方法触发BeanPostProcessor Bean的创建     //然后根据是否实现了PriorityOrdered接口、Ordered接口和其它分为三大类     //分别将这三大类的BeanPostProcessor实例进行注册     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 (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {             //这里调用BeanFactory.getBean()方法触发BeanPostProcessor Bean的创建             BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);             priorityOrderedPostProcessors.add(pp);             if (pp instanceof MergedBeanDefinitionPostProcessor) {                 internalPostProcessors.add(pp);             }         }         else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {             orderedPostProcessorNames.add(ppName);         }         else {             nonOrderedPostProcessorNames.add(ppName);         }     }      //首先注册实现了PriorityOrdered接口的BeanPostProcessor     sortPostProcessors(priorityOrderedPostProcessors, beanFactory);     registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);      //然后触发实现了Ordered接口的BeanPostProcessor Bean的创建并注册     List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());     for (String ppName : orderedPostProcessorNames) {         BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);         orderedPostProcessors.add(pp);         if (pp instanceof MergedBeanDefinitionPostProcessor) {             internalPostProcessors.add(pp);         }     }     sortPostProcessors(orderedPostProcessors, beanFactory);     registerBeanPostProcessors(beanFactory, orderedPostProcessors);      //最后触发其它BeanPostProcessor Bean的创建并注册     List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());     for (String ppName : nonOrderedPostProcessorNames) {         BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);         nonOrderedPostProcessors.add(pp);         if (pp instanceof MergedBeanDefinitionPostProcessor) {             internalPostProcessors.add(pp);         }     }     registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);      sortPostProcessors(internalPostProcessors, beanFactory);     registerBeanPostProcessors(beanFactory, internalPostProcessors); } 

CommonAnnotationBeanPostProcessor 实现逻辑(以修饰字段为例)

首先在 CommonAnnotationBeanPostProcessor 的静态初始化块中初始化了它要处理的注解。代码如下:

static {     //这里是为了适配不同版本@Resource注解在不同的包路径下     jakartaResourceType = loadAnnotationType("jakarta.annotation.Resource");     if (jakartaResourceType != null) {         resourceAnnotationTypes.add(jakartaResourceType);     }      //这里是为了适配不同版本@Resource注解在不同的包路径下     javaxResourceType = loadAnnotationType("javax.annotation.Resource");     if (javaxResourceType != null) {         resourceAnnotationTypes.add(javaxResourceType);     } } 

在它的 postProcessProperties() 方法中主要实现逻辑为找到 @Resource 注解修饰的字段 -> 通过反射给字段赋值。代码如下:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {     //找@Resource注解修饰的字段     InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);     try {         //给字段赋值         metadata.inject(bean, beanName, pvs);     }     catch (Throwable ex) {         throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);     }     return pvs; } 

@Resource 注解修饰的字段是在 findResourceMetadata() 方法中实现的,在该方法中又调用了 buildResourceMetadata() 来进行实际的查找,在这个方法中通过反射的方式遍历字段看它是否有 @Resource 注解修饰,如果是的话把它包装为一个 ResourceElement 对象放到列表中。最后基于列表构造一个 InjectionMetadata 对象返回。代码如下:

private InjectionMetadata findResourceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {     String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());     InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);     if (InjectionMetadata.needsRefresh(metadata, clazz)) {         synchronized (this.injectionMetadataCache) {             metadata = this.injectionMetadataCache.get(cacheKey);             if (InjectionMetadata.needsRefresh(metadata, clazz)) {                 if (metadata != null) {                     metadata.clear(pvs);                 }                 //这里调用buildResourceMetadata()方法                 metadata = buildResourceMetadata(clazz);                 this.injectionMetadataCache.put(cacheKey, metadata);             }         }     }     return metadata; }  private InjectionMetadata buildResourceMetadata(Class<?> clazz) {     List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();     Class<?> targetClass = clazz;      //省略部分代码          do {         final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();         //这里就会遍历每个字段看字段是否有@Resource注解修饰有的话就加入到列表中         ReflectionUtils.doWithLocalFields(targetClass, field -> {            //省略部分代码                         if (jakartaResourceType != null && field.isAnnotationPresent(jakartaResourceType)) {                 if (Modifier.isStatic(field.getModifiers())) {                     throw new IllegalStateException("@Resource annotation is not supported on static fields");                 }                 if (!this.ignoredResourceTypes.contains(field.getType().getName())) {                     currElements.add(new ResourceElement(field, field, null));                 }             }             else if (javaxResourceType != null && field.isAnnotationPresent(javaxResourceType)) {                 if (Modifier.isStatic(field.getModifiers())) {                     throw new IllegalStateException("@Resource annotation is not supported on static fields");                 }                 if (!this.ignoredResourceTypes.contains(field.getType().getName())) {                     currElements.add(new LegacyResourceElement(field, field, null));                 }             }         });         elements.addAll(0, currElements);         targetClass = targetClass.getSuperclass();     }     while (targetClass != null && targetClass != Object.class);      return InjectionMetadata.forElements(elements, clazz); } 

实际触发赋值的操作是在 InjectionMetadatainject() 方法中实现的,在它的方法中又会循环调用 InjectedElementinject() 方法。代码如下:

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

InjectedElementinject() 方法中通过反射的方式将找到的 Bean 赋值给字段。代码如下:

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) 	throws Throwable {     if (!shouldInject(pvs)) {         return;     }     if (this.isField) {         Field field = (Field) this.member;         ReflectionUtils.makeAccessible(field);         //这里通过反射的方式设置值,设置的值就是根据Bean名称获取到的Bean         field.set(target, getResourceToInject(target, requestingBeanName));     } else {         //省略其它代码     } } 

ResourceElementgetResourceToInject() 方法中实现了查找逻辑:如果 BeanFactory 中包含这个 Bean 名称对应的 Bean 则直接根据名称查找,否则会根据类型进行匹配,这个就是常说的 @Resource 注解默认是按照名称进行匹配的,名称匹配不到的情况下再按照类型进行匹配。代码如下:

protected Object getResource(LookupElement element, @Nullable String requestingBeanName)     throws NoSuchBeanDefinitionException {     //省略代码      // Regular resource autowiring     if (this.resourceFactory == null) {         throw new NoSuchBeanDefinitionException(element.lookupType,                 "No resource factory configured - specify the 'resourceFactory' property");     }     return autowireResource(this.resourceFactory, element, requestingBeanName); }  protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName) 	throws NoSuchBeanDefinitionException {     Object resource;     Set<String> autowiredBeanNames;     String name = element.name;      if (factory instanceof AutowireCapableBeanFactory autowireCapableBeanFactory) {         //如果根据Bean名称找不到Bean且允许按照类型匹配的情况下走第一个分支         if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {             autowiredBeanNames = new LinkedHashSet<>();             resource = autowireCapableBeanFactory.resolveDependency(                     element.getDependencyDescriptor(), requestingBeanName, autowiredBeanNames, null);             if (resource == null) {                 throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");             }         } else { //如果根据名称找得到Bean则直接根据名称获取Bean             resource = autowireCapableBeanFactory.resolveBeanByName(name, element.getDependencyDescriptor());             autowiredBeanNames = Collections.singleton(name);         }     } else {         //省略代码     }      //省略代码     return resource; } 

按照类型匹配的逻辑是在 DefaultListableBeanFactorydoResolveDependency() 方法中实现的,在该方法中会根据类型找到所有是当前类型的 Bean,然后构造一个 Map,key 是 Bean 的名称,value 是对应的 Bean 对象,如果找到的 Bean 个数大于 1 则会选择一个最符合条件的返回(选择的依据后面会讲到),如果等于 1 则直接返回这个 Bean。代码如下:

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, 	@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { 	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); 	try { 		//省略代码 		 		//这里根据类型找到所有的Bean,然后Bean的名称作为key,Bean作为Value 		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); 		if (matchingBeans.isEmpty()) { 			// 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.getResolvableType(), descriptor); 			} 			return null; 		}  		String autowiredBeanName; 		Object instanceCandidate;  		//如果根据类型找到多个Bean则需要选择一个合适的Bean返回 		if (matchingBeans.size() > 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 descriptor.resolveNotUnique(descriptor.getResolvableType(), 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 = matchingBeans.get(autowiredBeanName); 		} else { 			//如果只有一个Bean则直接返回这个Bean 			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); 			autowiredBeanName = entry.getKey(); 			instanceCandidate = entry.getValue(); 		}  		// Step 6: validate single result 		if (autowiredBeanNames != null) { 			autowiredBeanNames.add(autowiredBeanName); 		} 		if (instanceCandidate instanceof Class) { 			instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); 		} 		return resolveInstance(instanceCandidate, descriptor, type, autowiredBeanName); 	} 	finally { 		ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); 	} } 

AutowiredAnnotationBeanPostProcessor 实现逻辑(以修饰字段为例)

首先在构造函数中初始化了需要处理的注解包括 @Autowired@Inject 注解。代码如下:

public AutowiredAnnotationBeanPostProcessor() {     //添加要处理@Autowired注解     this.autowiredAnnotationTypes.add(Autowired.class);     this.autowiredAnnotationTypes.add(Value.class);      ClassLoader classLoader = AutowiredAnnotationBeanPostProcessor.class.getClassLoader();     try {         //这里是为了适配不同版本@Inject注解在不同的包路径下         this.autowiredAnnotationTypes.add((Class<? extends Annotation>)                 ClassUtils.forName("jakarta.inject.Inject", classLoader));     } catch (ClassNotFoundException ex) {         // jakarta.inject API not available - simply skip.     }      try {         //这里是为了适配不同版本@Inject注解在不同的包路径下         this.autowiredAnnotationTypes.add((Class<? extends Annotation>)                 ClassUtils.forName("javax.inject.Inject", classLoader));     } catch (ClassNotFoundException ex) {         // javax.inject API not available - simply skip.     } } 

在它的 postProcessProperties() 方法中主要实现逻辑为找到 @Autowired 或者 @Inject 注解修饰的字段 -> 通过反射给字段赋值。代码如下:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {     InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);     try {         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; } 

@Autowired 或者 @Inject 注解修饰的字段是在 findAutowiringMetadata() 方法中实现的,在该方法中又调用了 buildAutowiringMetadata() 来进行实际的查找,在这个方法中通过反射的方式遍历字段看它是否有 @Autowired 或者 @Inject 注解修饰,如果是的话把它包装为一个AutowiredFieldElement 对象放到列表中。最后基于列表构造一个 InjectionMetadata 对象返回。代码如下:

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {     // Fall back to class name as cache key, for backwards compatibility with custom callers.     String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());     // Quick check on the concurrent map first, with minimal locking.     InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);     if (InjectionMetadata.needsRefresh(metadata, clazz)) {         synchronized (this.injectionMetadataCache) {             metadata = this.injectionMetadataCache.get(cacheKey);             if (InjectionMetadata.needsRefresh(metadata, clazz)) {                 if (metadata != null) {                     metadata.clear(pvs);                 }                 metadata = buildAutowiringMetadata(clazz);                 this.injectionMetadataCache.put(cacheKey, metadata);             }         }     }     return metadata; }  private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {     if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {         return InjectionMetadata.EMPTY;     }      final List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();     Class<?> targetClass = clazz;      do {         final List<InjectionMetadata.InjectedElement> fieldElements = new ArrayList<>();         ReflectionUtils.doWithLocalFields(targetClass, field -> {             //这里找到是否有@Autowired或者@Inject注解修饰             MergedAnnotation<?> ann = findAutowiredAnnotation(field);             if (ann != null) {                 if (Modifier.isStatic(field.getModifiers())) {                     return;                 }                 boolean required = determineRequiredStatus(ann);                 fieldElements.add(new AutowiredFieldElement(field, required));             }         });     } } 

实际触发赋值的操作是在 InjectionMetadatainject() 方法中实现的,在它的方法中又会循环调用 AutowiredFieldElementinject() 方法。代码如下:

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

InjectedElementinject() 方法中通过反射的方式将找到的 Bean 赋值给字段。代码如下:

@Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {     Field field = (Field) this.member;     Object value;     if (this.cached) {         //省略代码     } else {         //找到对应的Bean         value = resolveFieldValue(field, bean, beanName);     }     if (value != null) {         ReflectionUtils.makeAccessible(field);         //通过反射的方式赋值         field.set(bean, value);     } }  @Nullable private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {     DependencyDescriptor desc = new DependencyDescriptor(field, this.required);     desc.setContainingClass(bean.getClass());     Set<String> autowiredBeanNames = new LinkedHashSet<>(2);     TypeConverter typeConverter = beanFactory.getTypeConverter();     Object value;     try {         //调用beanFactory的resolveDependency()方法         value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);     } catch (BeansException ex) {         throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);     }     return value; } 

然后会调用到 DefaultListableBeanFactorydoResolveDependency() 方法,和上面 @Resource 注解根据名称找不到 Bean 需要根据类型进行匹配的调用的是一个方法,只是它会多一个分支。在这个分支里面判断 Bean 名称对应的 Bean 是否存在,如果存在则直接返回,如果不存在才会按照类型去匹配,这里实际上还是先按照名称匹配的,名称匹配不上再走的类型匹配的逻辑。代码如下:

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, 	@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { 	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); 	try { 		//省略代码          //如果是@Autowired注解或者@Inject注解会先走到下面这个分支         //在这个分支里面也会先判断对应Bean名称的Bean是否存在,如果存在         //则直接获取返回,如果不存在才会按照类型去匹配         if (descriptor.usesStandardBeanLookup()) {             String dependencyName = descriptor.getDependencyName();             if (dependencyName == null || !containsBean(dependencyName)) {                 String suggestedName = getAutowireCandidateResolver().getSuggestedName(descriptor);                 dependencyName = (suggestedName != null && containsBean(suggestedName) ? suggestedName : null);             }             if (dependencyName != null) {                 dependencyName = canonicalName(dependencyName);  // dependency name can be alias of target name                 if (isTypeMatch(dependencyName, type) && isAutowireCandidate(dependencyName, descriptor) &&                         !isFallback(dependencyName) && !hasPrimaryConflict(dependencyName, type) &&                         !isSelfReference(beanName, dependencyName)) {                     if (autowiredBeanNames != null) {                         autowiredBeanNames.add(dependencyName);                     }                     Object dependencyBean = getBean(dependencyName);                     return resolveInstance(dependencyBean, descriptor, type, dependencyName);                 }             }         }          		//这里根据类型找到所有的Bean,然后Bean的名称作为key,Bean作为Value 		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); 		if (matchingBeans.isEmpty()) { 			// 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.getResolvableType(), descriptor); 			} 			return null; 		}  		String autowiredBeanName; 		Object instanceCandidate;  		//如果根据类型找到多个Bean则需要选择一个合适的Bean返回 		if (matchingBeans.size() > 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 descriptor.resolveNotUnique(descriptor.getResolvableType(), 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 = matchingBeans.get(autowiredBeanName); 		} else { 			//如果只有一个Bean则直接返回这个Bean 			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); 			autowiredBeanName = entry.getKey(); 			instanceCandidate = entry.getValue(); 		}  		// Step 6: validate single result 		if (autowiredBeanNames != null) { 			autowiredBeanNames.add(autowiredBeanName); 		} 		if (instanceCandidate instanceof Class) { 			instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); 		} 		return resolveInstance(instanceCandidate, descriptor, type, autowiredBeanName); 	} 	finally { 		ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); 	} } 

当有多个类型匹配的 Bean 选择返回一个 Bean 的原则

当根据类型找到多个 Bean 时需要根据一些规则返回一个Bean。常见的可以通过 @Qualifer 限定名称或者通过 @Primary 来表示优先注入。在DefaultListableBeanFactordetermineAutowireCandidate() 方法中就实现了这些逻辑:

首先遍历找到的所有符合类型的 Bean,然后看是否有 @Primary 注解修饰,如果有的话,则优先返回有该 Bean;

否则再次尝试根据字段的名称匹配看是否有匹配的 Bean,如果有则返回;

否则尝试获取 @Qualifier注解定义的名称(对于 @Named 注解来说它本身上面也有 @Qualifer 注解修饰),然后看是否有名称匹配的 Bean,如果有则返回;

否则遍历 Bean 看是否有 @Priority 注解修饰,如果有则找最高优先级的 Bean 返回,值越小优先级越高;

否则看 resolvableDependencies 是否有注册对应的实例,如果有则返回,它的使用场景一般是有用户自己的 new 的对象可以注册到这里面,然后在一个 Spring 管理的 Bean 中可以把它注入进来。代码如下:

protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {     Class<?> requiredType = descriptor.getDependencyType();     //首先处理@Primary注解,如果某个Bean有@Primary注解修饰则优先返回它     String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);     if (primaryCandidate != null) {         return primaryCandidate;     }     //否则再次根据字段的名称进行匹配,看找到的Bean里面有没有和字段名称相同的Bean,有的话则优先返回     String dependencyName = descriptor.getDependencyName();     if (dependencyName != null) {         for (String beanName : candidates.keySet()) {             if (matchesBeanName(beanName, dependencyName)) {                 return beanName;             }         }     }     //否则尝试获取@Qualifier注解定义的名称,看找打的Bean里面有没有和该名称相同的Bean,有的话则优先返回     String suggestedName = getAutowireCandidateResolver().getSuggestedName(descriptor);     if (suggestedName != null) {         for (String beanName : candidates.keySet()) {             if (matchesBeanName(beanName, suggestedName)) {                 return beanName;             }         }     }     //否则看找到的Bean是否有@Priority注解修饰,有的话取优先级最高的返回即值最小的     String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);     if (priorityCandidate != null) {         return priorityCandidate;     }     //否则自定义注册的非Spring管理生命周期的对象中是否有匹配,resolvableDependencies里面可以放     //一些对象,这些对象不是由Spring创建的而是用户自己创建放入的且需要在一个Spring的Bean中注入它     for (Map.Entry<String, Object> entry : candidates.entrySet()) {         String candidateName = entry.getKey();         Object beanInstance = entry.getValue();         if (beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) {             return candidateName;         }     }     return null; }  

@Named 注解定义中使用了 @Qualifer 注解修饰。代码如下:

@Qualifier // 这里使用了@Qualifer注解修饰 @Documented @Retention(RUNTIME) public @interface Named {     String value() default ""; } 

发表评论

评论已关闭。

相关文章