Spring(五)resolveDependency方法源码分析(byType、@Autowire自动装配)

目录

  • byType源码分析
  • @Autowired注解自动装配过程
    • 使用方式
    • 抛出问题
  • @Autowired源码分析
  • 第1步:MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition源码分析
    • 第1-1步:findAutowiringMetadata在Bean中找到所有@Autowire注解的元数据
    • 第1-2步:checkConfigMembers检查元数据中的信息
  • 第2步:InstantiationAwareBeanPostProcessor#postProcessPropertyValues
    • 第2-1步:findAutowiringMetadata找到所有的@Autowire注解的元数据(从injectionMetadataCache缓存获取)
    • 第2-2步:inject属性注入
  • resolveDependency方法
    • 第1步:findAutowireCandidates,通过Type在工厂中找到所有的候选Bean
    • 第3步:Type为普通类型,根据符合的Bean个数做处理
      • 第3-3步:determineAutowireCandidate在多个候选Bean中选择
  • 总结

byType源码分析

protected void autowireByType(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}

		Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			try {
				PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
				// Don't try autowiring by type for type Object: never makes sense,
				// even if it technically is a unsatisfied, non-simple property.
				if (Object.class != pd.getPropertyType()) {
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
					// Do not allow eager init for type matching in case of a prioritized post-processor.
					boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
					if (autowiredArgument != null) {
						pvs.add(propertyName, autowiredArgument);
					}
					for (String autowiredBeanName : autowiredBeanNames) {
						registerDependentBean(autowiredBeanName, beanName);
						if (logger.isDebugEnabled()) {
							logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
									propertyName + "' to bean named '" + autowiredBeanName + "'");
						}
					}
					autowiredBeanNames.clear();
				}
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
			}
		}
	}

根据类型自动装配:

  • 首先得到 所有需要装配的非简单属性 ,(不是字符串等简单类型)也就是Bean类型的属性,并返回
  • 检查此属性的set方法,存在的时候才可自动装配
  • 创建一个AutowireByType类型的依赖描述符
  • resolveDependency:解析依赖关系 ,返回依赖的Bean实例,这个方法在本篇最后分析。
  • 保存返回的依赖Bean实例:pvs.add(propertyName, autowiredArgument)
  • 记录依赖关系
  • (最后将在applyPropertyValues中实现pvs中的属性注入)

注意,其中有一行DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);

/**
	 * Special DependencyDescriptor variant for Spring's good old autowire="byType" mode.
	 * Always optional; never considering the parameter name for choosing a primary candidate.
	 */
	@SuppressWarnings("serial")
	private static class AutowireByTypeDependencyDescriptor extends DependencyDescriptor {

		public AutowireByTypeDependencyDescriptor(MethodParameter methodParameter, boolean eager) {
			super(methodParameter, false, eager);
		}

		@Override
		public String getDependencyName() {
			return null;
		}
	}

表示byType形式的依赖描述符有一种特殊的表示: 在选择主要候选对象时从不考虑参数名称!
这句话什么意思呢,就是使用byType形式的自动装配,当此Type的Bean有多个时,将会直接抛出错误,而不是再根据参数的Name去匹配第二遍。
主要是与@Autowired形式的属性注入的特点形成对比,具体分析如下。

@Autowired注解自动装配过程

@Autowired 可以对成员变量、方法以及构造函数进行注释。我们在日常开发的过程中主要使用的是对成员变量的自动装配,即先使用默认构造器创建实例之后,再通过注解使用setter注入属性。

使用方式

@Component
public class Cat {

    public String toString() {
        return "miao";
    }

}
@Component
public class Animal {

    @Autowired
    private Cat cat;

    public Cat getCat() {
        return this.cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }
}
public class MainTest {

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
        Animal animal = ac.getBean(Animal.class);
        System.out.println(animal.getCat().toString());
    }

}

 <context:component-scan base-package="*"/>

抛出问题

由上文可知,实现@Autowire类型属性注入的后处理器是AutowiredAnnotationBeanPostProcessor,该接口继承了InstantiationAwareBeanPostProcessor,实现了postProcessPropertyValues方法。

  • AutowiredAnnotationBeanPostProcessor何时被注册?
    当解析xml配置文件的标签时,会将AutowiredAnnotationBeanPostProcessor注册到工厂。
  • AutowiredAnnotationBeanPostProcessor何时被调用?
    对于@Autowire注解的属性注入,在整个Bean的属性填充中分为两个步骤:
    1. 注解的解析
    在Spring(四)doCreateBean方法源码分析的第2步:当创建完初始实例之后 ,会进行applyMergedBeanDefinitionPostProcessors:获取全部的MergedBeanDefinitionPostProcessor,然后遍历执行其postProcessMergedBeanDefinition方法。这个方法的意义为对MergedBeanDefinition进行修改,即对 bean定义 进行后期处理。
    AutowiredAnnotationBeanPostProcessor继承了MergedBeanDefinitionPostProcessor,在AutowiredAnnotationBeanPostProcessor中的实现即为:对@Autowire注解的Field及Method进行解析,并放入 injectionMetadataCache缓存 中。
    2. 属性的注入
    在Spring(四)doCreateBean方法源码分析中的第4-3步:InstantiationAwareBeanPostProcessor.postProcessPropertyValues。
    AutowiredAnnotationBeanPostProcessor继承了InstantiationAwareBeanPostProcessor,在AutowiredAnnotationBeanPostProcessor中的实现即为:找到被Autowired注解的属性(从injectionMetadataCache缓存中获取),进行属性注入。

@Autowired源码分析

第1步:MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition源码分析

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		if (beanType != null) {
			InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
			metadata.checkConfigMembers(beanDefinition);
		}
	}

方法包括了:

  1. findAutowiringMetadata在Bean中找到所有@Autowire注解的元数据
  2. checkConfigMembers检查元数据中的信息

第1-1步:findAutowiringMetadata在Bean中找到所有@Autowire注解的元数据

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, 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);
					}
					try {
						metadata = buildAutowiringMetadata(clazz);
						this.injectionMetadataCache.put(cacheKey, metadata);
					}
					catch (NoClassDefFoundError err) {
						throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +
								"] for autowiring metadata: could not find class that it depends on", err);
					}
				}
			}
		}
		return metadata;
	}

目标元数据使用缓存存储,关键的解析注解生成元数据的方法是buildAutowiringMetadata:

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
		Class<?> targetClass = clazz;

		do {
			final LinkedList<InjectionMetadata.InjectedElement> currElements =
					new LinkedList<InjectionMetadata.InjectedElement>();

			ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
				@Override
				public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
					AnnotationAttributes ann = findAutowiredAnnotation(field);
					if (ann != null) {
						if (Modifier.isStatic(field.getModifiers())) {
							if (logger.isWarnEnabled()) {
								logger.warn("Autowired annotation is not supported on static fields: " + field);
							}
							return;
						}
						boolean required = determineRequiredStatus(ann);
						currElements.add(new AutowiredFieldElement(field, required));
					}
				}
			});

			ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
				@Override
				public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
					Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
					if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
						return;
					}
					AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
					if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
						if (Modifier.isStatic(method.getModifiers())) {
							if (logger.isWarnEnabled()) {
								logger.warn("Autowired annotation is not supported on static methods: " + method);
							}
							return;
						}
						if (method.getParameterTypes().length == 0) {
							if (logger.isWarnEnabled()) {
								logger.warn("Autowired annotation should be used on methods with parameters: " + method);
							}
						}
						boolean required = determineRequiredStatus(ann);
						PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
						currElements.add(new AutowiredMethodElement(method, required, pd));
					}
				}
			});

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		return new InjectionMetadata(clazz, elements);
	}

关注上半部分,doWithLocalFields,找到Bean中带有注解的属性。其中的findAutowiredAnnotation是通过匹配注解找属性的方法。
找到之后进行两个操作:

  • 判断属性是否是Static,如果是静态的,则抛出错误
  • 判断属性是否是required,将Required与Field一起包装成AutowiredFieldElement返回

最后将找到的被注解Field存入到 injectionMetadataCache 中,以供真正的属性注入时使用。

第1-2步:checkConfigMembers检查元数据中的信息

public void checkConfigMembers(RootBeanDefinition beanDefinition) {
		Set<InjectedElement> checkedElements = new LinkedHashSet<InjectedElement>(this.injectedElements.size());
		for (InjectedElement element : this.injectedElements) {
			Member member = element.getMember();
			if (!beanDefinition.isExternallyManagedConfigMember(member)) {
				beanDefinition.registerExternallyManagedConfigMember(member);
				checkedElements.add(element);
				if (logger.isDebugEnabled()) {
					logger.debug("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
				}
			}
		}
		this.checkedElements = checkedElements;
	}

遍历上一步中Elements属性,将其注册到BeanDefinition的 externallyManagedConfigMembers,checkedElements 属性中以供后续使用。

第2步:InstantiationAwareBeanPostProcessor#postProcessPropertyValues

public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			metadata.inject(bean, beanName, pvs);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}

此方法中包括了:

  1. findAutowiringMetadata找到所有的@Autowire注解的元数据
  2. inject属性注入

第2-1步:findAutowiringMetadata找到所有的@Autowire注解的元数据(从injectionMetadataCache缓存获取)

第2-2步:inject属性注入

public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> elementsToIterate =
				(this.checkedElements != null ? this.checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			boolean debug = logger.isDebugEnabled();
			for (InjectedElement element : elementsToIterate) {
				if (debug) {
					logger.debug("Processing injected element of bean '" + beanName + "': " + element);
				}
				element.inject(target, beanName, pvs);
			}
		}
	}

此方法中:遍历BeanDefinition中解析到的checkedElements,依次进行element.inject(target, beanName, pvs);
Field类型的Element会进入到AutowiredFieldElement.inject方法:

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			try {
				Object value;
				if (this.cached) {
					value = resolvedCachedArgument(beanName, this.cachedFieldValue);
				}
				else {
					DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
					desc.setContainingClass(bean.getClass());
					Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
					TypeConverter typeConverter = beanFactory.getTypeConverter();
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
					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();
									if (beanFactory.containsBean(autowiredBeanName)) {
										if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
											this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
										}
									}
								}
							}
							else {
								this.cachedFieldValue = null;
							}
							this.cached = true;
						}
					}
				}
				if (value != null) {
					ReflectionUtils.makeAccessible(field);
					field.set(bean, value);
				}
			}
			catch (Throwable ex) {
				throw new BeanCreationException("Could not autowire field: " + field, ex);
			}
		}

根据@Autowire注解装配:

  • 首先 在缓存中找到所有被@Autowire注解的属性
  • 创建一个依赖描述符
  • resolveDependency:解析依赖关系 ,返回依赖的Bean实例
  • 记录依赖关系
  • 在此处直接通过 反射 给Bean的属性赋值

注意,这种依赖描述符无特殊处理,getDependencyName会返回Filed的名字,默认实现:

/**
	 * Determine the name of the wrapped parameter/field.
	 * @return the declared name (never {@code null})
	 */
	public String getDependencyName() {
		return (this.field != null ? this.field.getName() : this.methodParameter.getParameterName());
	}

resolveDependency方法

resolveDependency主要是通过Type类型,来解析依赖关系。用于byType类型的自动装配、@Autowired注解方式的自动装配。
resolveDependency方法中的核心步骤doResolveDependency:

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

		Class<?> type = descriptor.getDependencyType();
		Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
		if (value != null) {
			if (value instanceof String) {
				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()));
		}

		if (type.isArray()) {
			Class<?> componentType = type.getComponentType();
			DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
			targetDesc.increaseNestingLevel();
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc);
			if (matchingBeans.isEmpty()) {
				if (descriptor.isRequired()) {
					raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);
				}
				return null;
			}
			if (autowiredBeanNames != null) {
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			Object result = converter.convertIfNecessary(matchingBeans.values(), type);
			if (getDependencyComparator() != null && result instanceof Object[]) {
				Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans));
			}
			return result;
		}
		else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
			Class<?> elementType = descriptor.getCollectionType();
			if (elementType == null) {
				if (descriptor.isRequired()) {
					throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");
				}
				return null;
			}
			DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
			targetDesc.increaseNestingLevel();
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, targetDesc);
			if (matchingBeans.isEmpty()) {
				if (descriptor.isRequired()) {
					raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);
				}
				return null;
			}
			if (autowiredBeanNames != null) {
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			Object result = converter.convertIfNecessary(matchingBeans.values(), type);
			if (getDependencyComparator() != null && result instanceof List) {
				Collections.sort((List<?>) result, adaptDependencyComparator(matchingBeans));
			}
			return result;
		}
		else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
			Class<?> keyType = descriptor.getMapKeyType();
			if (String.class != keyType) {
				if (descriptor.isRequired()) {
					throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
							"] must be [java.lang.String]");
				}
				return null;
			}
			Class<?> valueType = descriptor.getMapValueType();
			if (valueType == null) {
				if (descriptor.isRequired()) {
					throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");
				}
				return null;
			}
			DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
			targetDesc.increaseNestingLevel();
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, targetDesc);
			if (matchingBeans.isEmpty()) {
				if (descriptor.isRequired()) {
					raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);
				}
				return null;
			}
			if (autowiredBeanNames != null) {
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			return matchingBeans;
		}
		else {
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (descriptor.isRequired()) {
					raiseNoSuchBeanDefinitionException(type, "", descriptor);
				}
				return null;
			}
			if (matchingBeans.size() > 1) {
				String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (primaryBeanName == null) {
					throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
				}
				if (autowiredBeanNames != null) {
					autowiredBeanNames.add(primaryBeanName);
				}
				return matchingBeans.get(primaryBeanName);
			}
			// We have exactly one match.
			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(entry.getKey());
			}
			return entry.getValue();
		}
	}

方法很长,包括如下功能:

  1. findAutowireCandidates,找到 所有匹配Type的所有Bean ,返回matchingBeans:一个Map
  2. 如果属性的类型是「数组、集合、Map」,只要matchingBeans不为空则直接返回
  3. 重点看依赖是普通Bean类型的情况

第1步:findAutowireCandidates,通过Type在工厂中找到所有的候选Bean

protected Map<String, Object> findAutowireCandidates(
			String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {

		String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
				this, requiredType, true, descriptor.isEager());
		Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
		for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
			if (autowiringType.isAssignableFrom(requiredType)) {
				Object autowiringValue = this.resolvableDependencies.get(autowiringType);
				autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
				if (requiredType.isInstance(autowiringValue)) {
					result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
					break;
				}
			}
		}
		for (String candidateName : candidateNames) {
			if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
				result.put(candidateName, getBean(candidateName));
			}
		}
		if (result.isEmpty()) {
			DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
			for (String candidateName : candidateNames) {
				if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
					result.put(candidateName, getBean(candidateName));
				}
			}
		}
		return result;
	}

第3步:Type为普通类型,根据符合的Bean个数做处理

     Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (descriptor.isRequired()) {
					raiseNoSuchBeanDefinitionException(type, "", descriptor);
				}
				return null;
			}
			if (matchingBeans.size() > 1) {
				String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (primaryBeanName == null) {
					throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
				}
				if (autowiredBeanNames != null) {
					autowiredBeanNames.add(primaryBeanName);
				}
				return matchingBeans.get(primaryBeanName);
			}
			// We have exactly one match.
			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(entry.getKey());
			}
			return entry.getValue();
  1. 如果matchingBeans(即工厂中此Type的Bean)是空,而属性又是Required,则抛出错误;
  2. 如果matchingBeans正好为1个,则将此matchingBean加入到autowiredBeanNames中返回;
  3. 如果matchingBeans有多个,determineAutowireCandidate在多个候选Bean中选择一个,选择的策略为determineAutowireCandidate

第3-3步:determineAutowireCandidate在多个候选Bean中选择

protected String determineAutowireCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {
		Class<?> requiredType = descriptor.getDependencyType();
		String primaryCandidate = determinePrimaryCandidate(candidateBeans, requiredType);
		if (primaryCandidate != null) {
			return primaryCandidate;
		}
		String priorityCandidate = determineHighestPriorityCandidate(candidateBeans, requiredType);
		if (priorityCandidate != null) {
			return priorityCandidate;
		}
		// Fallback
		for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
			String candidateBeanName = entry.getKey();
			Object beanInstance = entry.getValue();
			if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
					matchesBeanName(candidateBeanName, descriptor.getDependencyName())) {
				return candidateBeanName;
			}
		}
		return null;
	}

可以很清晰地看到选择Bean的策略为:

  1. 找加了@Primary注解的bean;
  2. 找加了@Priority注解的bean;
  3. 根据属性的名称和Spring中的beanName是否相等来判断;
    如果上述三个方法都不能确定唯一的Bean,则会抛出异常
    在第三种情况中,判断两个name是否相等的代码:
matchesBeanName(candidateBeanName, descriptor.getDependencyName())

注意:byType类型的descriptor.getDependencyName(),上文已经说明,被重写为return null;所以byType类型的自动装配无论名字是否相同,最后都将返回空,也就是抛出错误:NoUniqueBeanDefinitionException。

所以说,@Autowired注解是先根据类型注入,当碰到多个相同类型时,就会根据属性名注入

总结

byType与Autowired注解是有些相似之处的

  • 它们的本质都是通过Type找到所有符合条件的Bean,然后再进行筛选。

不同之处在于

  • byType类型的自动装配是我们在xml中配置的属性标签所声明,在xml配置解析的过程中已经被解析到了BeanDefintion中;而@Autowired是一个注解,只能使用 后置处理器去解析注解 属性,进行处理。
  • byType类型的自动装配通过resolveDependency找到所依赖的Bean对象之后,会存入到PropertyValues中,等到属性填充方法populateBean的最后applyPropertyValues时再统一的应用;而@Autowired通过resolveDependency找到所依赖的Bean对象之后,会直接通过反射将属性赋值,而不再存入PropertyValues。
  • byType类型不会对属性名称进行判断;而@Autowired当找到有多个此类型的Bean时,会再按照属性名进行筛选。

你可能感兴趣的:(spring)