Spring源码系列(十九)Autowired注解的查找规则

1.写在前面

笔者上篇博客已经介绍了对应的属性注入的流程了,但是属性注入中@Autowired的注解的属性注入的查找对应的属性,这块笔者没有讲,这块也是@Autowired比较重要的部分。网上很多说@Autowired的注解是先根据类型找,然后如果类型找不到再根据名字找,那么从源码的角度来说,是不是对的呢?

2.一个简单的例子

笔者先创建一个接口I,然后写两个实现类B和C,这个时候再创建一个A类,在A类中我们注入I,然后看能不能注入成功,具体的代码如下:

package com.ys.autowiredDemo;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.ys.autowiredDemo")
public class AppConfig {
}

package com.ys.autowiredDemo;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    }
}

package com.ys.autowiredDemo;

public interface I {
}

package com.ys.autowiredDemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class A {

    @Autowired
    private I i;
}

package com.ys.autowiredDemo;

import org.springframework.stereotype.Component;

@Component
public class B implements I{
}

package com.ys.autowiredDemo;

import org.springframework.stereotype.Component;

@Component
public class C implements I{
}

运行的结果如下:

在这里插入图片描述

你会发现这儿直接报错了,于是笔者修改A类的代码,具体的如下:

package com.ys.autowiredDemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class A {

    @Autowired
    private I b;
}

再次运行程序,结果如下:

在这里插入图片描述

你会发现程序正常退出了,那么是不是就可以得到@Autowired注解是先根据类型找然后再根据名称找呢?从这个现象上来看,似乎答案就是这样的,这个时候我们需要看下源码来证明这个答案是否正确。

3.@Autowired注解属性的查找规则

上篇博客笔者已经谈到了属性注入,但是笔者没有具体将这块这个查找规则,废话不多说直接上代码

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	Field field = (Field) this.member;
	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<>(1);
		Assert.state(beanFactory != null, "No BeanFactory available");
		TypeConverter typeConverter = beanFactory.getTypeConverter();
		try {
            //查找对应属性
			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();
						if (beanFactory.containsBean(autowiredBeanName) &&
								beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
							this.cachedFieldValue = new ShortcutDependencyDescriptor(
									desc, autowiredBeanName, field.getType());
						}
					}
				}
				else {
					this.cachedFieldValue = null;
				}
				this.cached = true;
			}
		}
	}
	if (value != null) {
		ReflectionUtils.makeAccessible(field);
		field.set(bean, value);
		}
	}
}

上面的代码笔者上篇博客已经讲得差不多了,就这块的查找规则没有讲,主要的调用的方法就是beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);具体的代码如下:

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

    //初始化参数名称的发现器,因为java原生的api不能查出方法的参数名称
	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	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 Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
	}
	else {
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}

上面的主要分了几种情况,笔者还是每个都讲下吧!反正都是学习。

3.1注入的类型是Optional

笔者先将测试代码改成如下:

package com.ys.autowiredDemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Optional;

@Component
public class A {

    @Autowired
    private Optional<I> b;
}

这个时候的注入的类型是Optional于是会调用createOptionalDependency(descriptor, requestingBeanName);方法,具体的代码如下:

private Optional<?> createOptionalDependency(
		DependencyDescriptor descriptor, @Nullable String beanName, final Object... args) {

	DependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {
        //返回是否需要此依赖项
		@Override
		public boolean isRequired() {
			return false;
		}
        //解析Bean,父类就是调用getBean()
		@Override
		public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
			return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
					super.resolveCandidate(beanName, requiredType, beanFactory));
		}
	};
    //准备解析查找
	Object result = doResolveDependency(descriptorToUse, beanName, null, null);
    //若返回的结果是Optional就直接返回,如果不是就包装成一个Optional
	return (result instanceof Optional ? (Optional<?>) result : Optional.ofNullable(result));
}

这个时候会调用doResolveDependency(descriptorToUse, beanName, null, null);方法,来查找和解析,具体的代码如下:

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) {
			return shortcut;
		}
        
		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());
			try {
				return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
			}
			catch (UnsupportedOperationException ex) {
				// A custom TypeConverter which does not support TypeDescriptor resolution...
				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(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 {
			// 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) {
			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);
	}
}

由于上面的代码的篇幅过长,于是读者打算分成几部分来讲。第一部分如下:

//设置当前的注入点
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
//这个只有在前面设置了缓存,这个值才不为空
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
	return shortcut;
} 

所以上面的代码就是设置一个当前的注入点,后面调用的方法,只有在前面设置了缓存,这儿取出来的值才不为空,我们继续看剩下的部分

//获取注入的类型,注意这儿如果是泛型,会取出泛型的类
Class<?> type = descriptor.getDependencyType();
//@Value注解中value的值,笔者这儿没有给定Value的value的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
	if (value instanceof String) {
		String strVal = resolveEmbeddedValue((String) value);
        //获取这个时候的BeanDefinition
		BeanDefinition bd = (beanName != null && containsBean(beanName) ?
			getMergedBeanDefinition(beanName) : null);
        //判断这个字符串是表达式还是其他的
		value = evaluateBeanDefinitionString(strVal, bd);
		}
    //获取类型转换器
	TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
	try {
        //讲这个value进行转换,然后返回
		return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
	}
	catch (UnsupportedOperationException ex) {
		// A custom TypeConverter which does not support TypeDescriptor resolution...
		return (descriptor.getField() != null ?
			converter.convertIfNecessary(value, type, descriptor.getField()) :
			converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
	}
}

上面的那一段代码主要是@Value注解的解释,不是本篇博客的重点,笔者继续往下讲。

//这段代码主要是处理注入的类型是集合类型的,笔者后面会讲,这个时候这儿返回值就是null
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
	return multipleBeans;
}

//查找满足情况的注入的bean,也是我们本篇博客的重点
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
//如果没有找到同时也是必须注入的,就直接抛出异常
if (matchingBeans.isEmpty()) {
	if (isRequired(descriptor)) {
        //抛出异常
		raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
	}
	return null;
}

上面的代码走来是处理注入集合的情况,然后处理的是查找满足注入条件的所有bean,如果查出来的是空,同时这个属性也是必须注入的,就会直接抛出异常,如果不是一定要注入的,那么不抛出异常,直接返回null,这个时候我们需要看的就是查找的方法的findAutowireCandidates(beanName, type, descriptor);具体的代码如下:

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

    //先根据类型在spring容器中找对应beanName
	String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
			this, requiredType, true, descriptor.isEager());
    //创建结果的集合
	Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
    //判断是不是指定的四种类型,是的话添加到对应的结果集合
	for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
		Class<?> autowiringType = classObjectEntry.getKey();
		if (autowiringType.isAssignableFrom(requiredType)) {
			Object autowiringValue = classObjectEntry.getValue();
			autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
			if (requiredType.isInstance(autowiringValue)) {
				result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
				break;
			}
		}
	}
	for (String candidate : candidateNames) {
        //确定给定的beanName / candidateName对是否表示一个自引用,即候选对象是指向原始bean还是指向原始bean的工厂方法。
        //同时判断这个注入的对象是否符合自动装配
		if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
            //在候选映射中添加一个条目:一个bean实例(如果有的话)或只是解析的类型,以防止在选择主要候选对象之前尽早初始化bean。
			addCandidateEntry(result, candidate, descriptor, requiredType);
		}
	}
    //如果结果为空
	if (result.isEmpty()) {
        //判断注入的类型是数组,Collection,Map
		boolean multiple = indicatesMultipleBeans(requiredType);
        // 如果第一遍未找到任何内容,请考虑进行备用匹配...
		// Consider fallback matches if the first pass failed to find anything...
		DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
        //再找一遍
		for (String candidate : candidateNames) {
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
					(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}
		if (result.isEmpty() && !multiple) {
			// Consider self references as a final pass...
			// but in the case of a dependency collection, not the very same bean itself.
            //将自我引用视为最终通过... 
            //但是,如果是依赖项集合,则不是完全相同的bean本身。
			for (String candidate : candidateNames) {
				if (isSelfReference(beanName, candidate) &&
						(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
						isAutowireCandidate(candidate, fallbackDescriptor)) {
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
		}
	}
	return result;
}

上面代码主要是先根据类型找到对应的beanName,然后判断这个beanName是否是如下四种的类型。

在这里插入图片描述

然后会遍历找到的候选的beanName,然后遍历这些的beanName,然后判断给定的beanName / candidateName对是否表示一个自引用,即候选对象是指向原始bean还是指向原始bean的工厂方法。同时判断这个注入的对象是否符合自动装配。如果都满足的话,就直接调用addCandidateEntry(result, candidate, descriptor, requiredType);方法,具体的代码如下:

private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
		DependencyDescriptor descriptor, Class<?> requiredType) {

    //注入的对象是集合那种的,也是从容器中直接取
	if (descriptor instanceof MultiElementDescriptor) {
		Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
		if (!(beanInstance instanceof NullBean)) {
			candidates.put(candidateName, beanInstance);
		}
	}
    //这个时候这个bean已经注册好了
	else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
			((StreamDependencyDescriptor) descriptor).isOrdered())) {
        //这个时候直接从容器中去
		Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
		candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
	}
	else {
        //调用对应的getType方法,然后put到对应候选集合中
		candidates.put(candidateName, getType(candidateName));
	}
}

这个时候会根据不同的类型,然后调用对应的方法,进行添加到集合中,前面的两种都是通过getBean 的方法进行获取,主要讲的是最后的一种,主要调用是getType方法,具体的代码如下:

public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
    //获取对应的beanName
	String beanName = transformedBeanName(name);

	// Check manually registered singletons.
    //从单例池中获取
	Object beanInstance = getSingleton(beanName, false);
    //若不为空
	if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
        //然后分两种情况处理,一种是FactoryBean,一种是普通的bean,反正都是获取beanClass
		if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
			return getTypeForFactoryBean((FactoryBean<?>) beanInstance);
		}
		else {
			return beanInstance.getClass();
		}
	}

	// No singleton instance found -> check bean definition.
    // 找不到单例实例->检查bean定义
    // 获取父的工厂
	BeanFactory parentBeanFactory = getParentBeanFactory();
	if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
		// No bean definition found in this factory -> delegate to parent.
        //在此工厂中找不到bean定义->委托给父对象。同样在父工厂也是找一遍
		return parentBeanFactory.getType(originalBeanName(name));
	}

    //获取合并后的BeanDefinition
	RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

	// Check decorated bean definition, if any: We assume it'll be easier
	// to determine the decorated bean's type than the proxy's type.
    // 检查BeanDefinition 如果有的话:我们假设确定修饰的bean的类型比代理的类型更容易
    // 返回由此bean定义修饰的目标定义(如果有)。
	BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
	if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
		RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
		Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd);
		if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
			return targetClass;
		}
	}
    
    //预测beanClass
	Class<?> beanClass = predictBeanType(beanName, mbd);

	// Check bean class whether we're dealing with a FactoryBean.
    // 判断是否是FactoryBean类型,这个时候会分情况返回对应的类型
	if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) {
		if (!BeanFactoryUtils.isFactoryDereference(name)) {
			// If it's a FactoryBean, we want to look at what it creates, not at the factory class.
			return getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit).resolve();
		}
		else {
			return beanClass;
		}
	}
	else {
		return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass : null);
	}
}

上面的代码大致的流程就是先从容器中获取,如果有就直接返回,如果找不到,就从父容器中找,如果父容器中也找不到,那么就需要根据BeanDefinition来推断这个Bean的类型了,然后进行返回,如果还是空,就直接返回空,这个时候需要知道推断的方法 predictBeanType(beanName, mbd);具体的代码如下:

protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
    //推断出对应的类型
	Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch);
	// Apply SmartInstantiationAwareBeanPostProcessors to predict the
	// eventual type after a before-instantiation shortcut.
    // 调用对应的后置处理器
	if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        //这儿这个值是false,因为typesToMatch为空
		boolean matchingOnlyFactoryBean = typesToMatch.length == 1 && typesToMatch[0] == FactoryBean.class;
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
				SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
				Class<?> predicted = ibp.predictBeanType(targetType, beanName);
				if (predicted != null &&
						(!matchingOnlyFactoryBean || FactoryBean.class.isAssignableFrom(predicted))) {
					return predicted;
				}
			}
		}
	}
	return targetType;
}

上面先来推断出来类型,然后调用bean的后置处理器的predictBeanType方法来进一步确定返回的class,走来调用的是ImportAwareBeanPostProcessor类的predictBeanType的方法,具体的代码如下:

public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
	return null;
}

返回的是null,这个时候下面的判断不满足,于是就不会返回,继续执行下一个后置处理器AutowiredAnnotationBeanPostProcessorpredictBeanType方法,具体的代码如下:

public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
	return null;
}

返回的是null,这个时候下面的判断不满足,于是就不会返回,这个时候所有的后置处理器就执行完了,由于都是返回null,所以最终返回的还是调用determineTargetType(beanName, mbd, typesToMatch);方法找出来的Class。这个时候这个getType方法就讲完了。于是将这些找出来的Class存到候选对象的集合中去。继续看剩下的代码,具体的代码如下:

String autowiredBeanName;
Object instanceCandidate;

//根据类型找出来满足条件的大于1
if (matchingBeans.size() > 1) {
    //推断自动注入的beanName 
	autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    //如果推断出来是空的
	if (autowiredBeanName == null) {
        //判断是否是必须要注入的,或者不是注入多个那种,直接抛出异常
		if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
			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;
		}
	}
    //直接从刚才候选的集合中取出推断出来的Bean
	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();
}

如果找出来的候选对象大于一个,这个时候需要调用方法determineAutowireCandidate(matchingBeans, descriptor);再次推断一下,如果是只有一个直接进行赋值,这个时候需要解决我们开头的问题,我们需要看的方法就是determineAutowireCandidate(matchingBeans, descriptor);具体的代码如下:

protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
    //获取注入的类型
	Class<?> requiredType = descriptor.getDependencyType();
    //获取有没有加了@Primary注解类,如果有直接返回
	String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
	if (primaryCandidate != null) {
		return primaryCandidate;
	}
    //获取加了@Priority最高优先级的Bean,如果有直接返回
	String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
	if (priorityCandidate != null) {
		return priorityCandidate;
	}
	// Fallback
    // 这个时候就会根据beanName的名称去匹配,同时包括别名
	for (Map.Entry<String, Object> entry : candidates.entrySet()) {
		String candidateName = entry.getKey();
		Object beanInstance = entry.getValue();
		if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
				matchesBeanName(candidateName, descriptor.getDependencyName())) {
			return candidateName;
		}
	}
	return null;
}

由此我们可以得到对应匹配规则,显示根据类型从容器中找一遍,然后再根据上面的筛选规则从这个集合中再筛选一遍,最后返回对应的result,最后看剩下的代码,具体的代码如下:

//这个值默认传进来是null
if (autowiredBeanNames != null) {
	autowiredBeanNames.add(autowiredBeanName);
}
//这个值如果上面找出来,就不会为空
if (instanceCandidate instanceof Class) {
    //调用getBean方法
	instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
//判断结果是否为NullBean
if (result instanceof NullBean) {
    //如果是必须注入的话,直接抛出异常
	if (isRequired(descriptor)) {
		raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
	}
    //如果不是,直接赋值为null
	result = null;
}
//最后发现如果是不匹配的,直接抛出异常
if (!ClassUtils.isAssignableValue(type, result)) {
	throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;

上面的代码就是根据你找出来的beanName,调用一次getBean的方法,然后进行返回,至此整个注入的类型是Optional的类型的情况就讲完了。

3.2注入的类型是ObjectFactory

笔者带着大家看第三种情况,主要注入的类型是FactoryBean,具体的测试的代码如下:

package com.ys.autowiredDemo;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;

public class D implements ObjectFactory {
    @Override
    public Object getObject() throws BeansException {
        return new E();
    }
}

package com.ys.autowiredDemo;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class A {

    @Autowired
    private ObjectFactory<E> d;

    public ObjectFactory<E> getD() {
        return d;
    }
}

这个时候我们再回到原来的代码的地方,具体的代码如下:

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

	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	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 Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
	}
	else {
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}

这个以后调用的方法的分支就是第二个if的判断,主要调用的代码就是new DependencyObjectProvider(descriptor, requestingBeanName);具体的代码如下:

public DependencyObjectProvider(DependencyDescriptor descriptor, @Nullable String beanName) {
	this.descriptor = new NestedDependencyDescriptor(descriptor);
	this.optional = (this.descriptor.getDependencyType() == Optional.class);
	this.beanName = beanName;
}

其实就是创建了一个对象填充DependencyObjectProvider注入进去了,只有在调用这个对象的getObject()方法才会创建这个对应的对象,具体的代码如下:

public Object getObject() throws BeansException {
	if (this.optional) {
		return createOptionalDependency(this.descriptor, this.beanName);
	}
	else {
		Object result = doResolveDependency(this.descriptor, this.beanName, null, null);
		if (result == null) {
			throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
		}
		return result;
	}
}

上面的代码又是很熟悉的代码,和前面的一样,这儿获取的result就是前面的FactoryBean泛型中提供的值,如果没有提供值就会报错。

3.3注入的类型的是普通的类型

由于注入的是普通的类型,笔者在这儿就不写测试代码了,直接回到原来的代码的地方,具体的如下:

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

	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	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 Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
	}
	else {
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}

你会发现走来调用的是getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);方法,具体的代码如下:

public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
	return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);
}

主要判断这个注入的类是不是一个懒加载的类,如果是懒加载的类,就创建一个代理对象去填充到result中去,如果不是懒加载,又是会调用我们原来的方法。

3.4注入的类型是集合

注入的类型是集合的话,我们只需要看下doResolveDependency方法中在处理集合的方法resolveMultipleBeans具体的代码如下:

private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {

    //获取注入的类型
	Class<?> type = descriptor.getDependencyType();

    //是Stream流的处理方式
	if (descriptor instanceof StreamDependencyDescriptor) {
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		Stream<Object> stream = matchingBeans.keySet().stream()
				.map(name -> descriptor.resolveCandidate(name, type, this))
				.filter(bean -> !(bean instanceof NullBean));
		if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
			stream = stream.sorted(adaptOrderComparator(matchingBeans));
		}
		return stream;
	}
    //是数组
	else if (type.isArray()) {
        //获取注入的数组中的类型
		Class<?> componentType = type.getComponentType();
		ResolvableType resolvableType = descriptor.getResolvableType();
		Class<?> resolvedArrayType = resolvableType.resolve(type);
        //判断类型是否匹配
		if (resolvedArrayType != type) {
			componentType = resolvableType.getComponentType().resolve();
		}
		if (componentType == null) {
			return null;
		}
        //查找对应的bean
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
        //将beanName添加到指定的集合中
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
        //进行类型的转换
		TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
		Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
        //排序
		if (result instanceof Object[]) {
			Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
			if (comparator != null) {
				Arrays.sort((Object[]) result, comparator);
			}
		}
		return result;
	}
	else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { //集合
        //获取集合中填充的值
		Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
		if (elementType == null) {
			return null;
		}
        //调用查找的方法
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
        //将所有找出来的beanName添加到这个集合中
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
        //进行对应的类型装换
		TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
		Object result = converter.convertIfNecessary(matchingBeans.values(), type);
        //结果是list的话进行对应的排序
		if (result instanceof List) {
			if (((List<?>) result).size() > 1) {
				Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
				if (comparator != null) {
					((List<?>) result).sort(comparator);
				}
			}
		}
        //然后返回,这样集合的注入就完成了
		return result;
	}
	else if (Map.class == type) {//Map
        //获取map的type
		ResolvableType mapType = descriptor.getResolvableType().asMap();
        //获取键的类型
		Class<?> keyType = mapType.resolveGeneric(0);
        //键不是String的直接返回
		if (String.class != keyType) {
			return null;
		}
        //获取值的类型
		Class<?> valueType = mapType.resolveGeneric(1);
		if (valueType == null) {
			return null;
		}
        //根据值找beanName
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
        //添加到集合中去
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		return matchingBeans;
	}
	else {
		return null;
	}
}

多条数据的注入的方式就如笔者上面的注释的一样,至此整个@Autowired的查找规则就讲完了。

4.写在最后

本篇博客主要介绍spring中@Autowired的注解的查找的规则,也主要解释了一个问题,就是@Autowired的注解是先根据类型找,然后如果类型找不到再根据名字找,那么从源码的角度来说,是不是对的呢?想必读者看了这篇博客已经有了答案。

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值