spring 注解模式下对依赖的解析

在 spring 注解模式下,不管是采用 @Autowired 注入 bean,或者是采用 @Value 为 bean 中指定的 Field 注入值,亦或者在 @Bean 修饰的方法中携带参数,都会涉及到对依赖的 bean 或 值的解析。下面我们来看下,在 spring 中,对依赖的解析到底是怎么实现的。

resolveDependency

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

	// DefaultParameterNameDiscoverer
	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 {
		// ContextAnnotationAutowireCandidateResolver
		// AnnotationConfigUtils#registerAnnotationConfigProcessors 时设置
		// 判断是否持有 @Lazy 注解
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}

这里先来看看这个 DependencyDescriptor,依赖的描述,继承 InjectionPoint,是一个注入点。从构造方法可知,可作为注入点的共有两个,一个是 MethodParameter,表示方法注入,即 @Bean 修饰方法携带参数,或者 setter 方法上存在 @Value;另一个是 Field,即类中字段注入。不管是哪一种,最后都会封装成一个 DependencyDescriptor。

此处一般不持有 @Lazy 注解,所以调用 doResolveDependency 方法。

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

	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
	try {
		Object shortcut = descriptor.resolveShortcut(this);
		if (shortcut != null) {
			return shortcut;
		}

		// 获取依赖的类型
		// MethodParameter 为 @Bean 方法返回值类型
		Class<?> type = descriptor.getDependencyType();
		// ContextAnnotationAutowireCandidateResolver
		// 如果 @Value 中存在占位符 ${},此时解析返回的 value 中包含 ${}
		// 方法上只定义 @Bean,此时不持有 @Value,返回 null
		Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
		if (value != null) {
			// @Value String 类型,利用之前注册的 embeddedValueResolvers 进行解析
			if (value instanceof String) {
				// 占位符处理,得到真正的值
				String strVal = resolveEmbeddedValue((String) value);
				BeanDefinition bd = (beanName != null && containsBean(beanName) ?
						getMergedBeanDefinition(beanName) : null);
				// SpEl spring EL 表达处理
				value = evaluateBeanDefinitionString(strVal, bd);
			}
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			try {
				// 类型转换后直接返回
				return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
			}
			catch (UnsupportedOperationException ex) {
				// 自定义 TypeConverter 不支持 TypeDescriptor 时的解决方法
				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 {
			// 只有一个匹配到了
			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
			// beanName
			autowiredBeanName = entry.getKey();
			// beanClass 或 bean
			instanceCandidate = entry.getValue();
		}

		if (autowiredBeanNames != null) {
			autowiredBeanNames.add(autowiredBeanName);
		}
		if (instanceCandidate instanceof Class) {
			// 解析候选者,创建依赖的 bean 实例对象
			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);
	}
}

先获取依赖的类型。如果是 Field 注入, 就是字段定义的类型,此时调用 getAutowireCandidateResolver().getSuggestedValue 就能得到 @Value 注解的值。有一点需注意,如果值含有占位符,则会将包含占位符的字符串一并返回,然后利用之前注册的 embeddedValueResolvers 进行解析,得到真正的 value 值

@Override
@Nullable
public Object getSuggestedValue(DependencyDescriptor descriptor) {
	// 获取 Field 或 方法参数 上 @Value 注入的 value 值
	// 如果是 Field,此处即可获取 @Value 注入的 value 值
	// 如果是 Method,@Value 可存在于方法参数,也可存在于方法上,所以为 null,会获取方法注解之后,再调用 findValue
	Object value = findValue(descriptor.getAnnotations());
	if (value == null) {
		MethodParameter methodParam = descriptor.getMethodParameter();
		if (methodParam != null) {
			// 获取方法上的注解,解析 @Value 注入的 value 值
			value = findValue(methodParam.getMethodAnnotations());
		}
	}
	return value;
}
// InjectionPoint
// 获取 Field 或 @Bean 方法上注解
// 针对 MethodParameter 获取的是方法参数中的注解
public Annotation[] getAnnotations() {
	if (this.field != null) {
		Annotation[] fieldAnnotations = this.fieldAnnotations;
		if (fieldAnnotations == null) {
			fieldAnnotations = this.field.getAnnotations();
			this.fieldAnnotations = fieldAnnotations;
		}
		return fieldAnnotations;
	}
	else {
		return obtainMethodParameter().getParameterAnnotations();
	}
}

@Nullable
protected Object findValue(Annotation[] annotationsToSearch) {
	if (annotationsToSearch.length > 0) {
		// 获取 annotationsToSearch 中持有 @Value 注解的属性
		AnnotationAttributes attr = AnnotatedElementUtils.getMergedAnnotationAttributes(
				AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType);
		if (attr != null) {
			return extractValue(attr);
		}
	}
	return null;
}

如果是 Method 注入,则依赖的类型为方法参数类型。方法参数类型为基本类型或 String 时,通过getAutowireCandidateResolver().getSuggestedValue(descriptor); 就处理了。如果是一个 refBean,则需要 findAutowireCandidates 来处理。

// DefaultListableBeanFactory
protected Map<String, Object> findAutowireCandidates(
		@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
	
	// 根据指定类型获取 beanFactory 中注册的 BeanDefinition 对应的 beanName
	String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
			this, requiredType, true, descriptor.isEager());
	Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
	// resolvableDependencies 4 个
	// BeanFactory/ApplicationContext/ApplicationEventPublisher/ResourceLoader
	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) {
		// 判断是否是自引用
		if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
			addCandidateEntry(result, candidate, descriptor, requiredType);
		}
	}
	// result 不为空,直接返回 result
	if (result.isEmpty()) {
		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.
			for (String candidate : candidateNames) {
				if (isSelfReference(beanName, candidate) &&
						(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
						isAutowireCandidate(candidate, fallbackDescriptor)) {
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
		}
	}
	return result;
}

根据指定类型,即方法参数类型,获取 beanFactory 中注册的符合条件的 BeanDefinition 对应的 beanName,作为候选者名称 candidateNames。接着遍历 candidateNames,不是自引用,并且isAutowireCandidate 为 true,则执行 addCandidateEntry。

下面来看下 isAutowireCandidate 具体是如何判断的。

// DefaultListableBeanFactory
// 判断是否是注入候选者
protected boolean isAutowireCandidate(
		String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver)
		throws NoSuchBeanDefinitionException {

	String bdName = BeanFactoryUtils.transformedBeanName(beanName);
	if (containsBeanDefinition(bdName)) {
		return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(bdName), descriptor, resolver);
	}
	else if (containsSingleton(beanName)) {
		return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
	}

	BeanFactory parent = getParentBeanFactory();
	if (parent instanceof DefaultListableBeanFactory) {
		// No bean definition found in this factory -> delegate to parent.
		return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver);
	}
	else if (parent instanceof ConfigurableListableBeanFactory) {
		// If no DefaultListableBeanFactory, can't pass the resolver along.
		return ((ConfigurableListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor);
	}
	else {
		return true;
	}
}
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
		DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {

	String bdName = BeanFactoryUtils.transformedBeanName(beanName);
	resolveBeanClass(mbd, bdName);
	if (mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) {
		new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
	}
	// 创建一个 BeanDefinitionHolder
	BeanDefinitionHolder holder = (beanName.equals(bdName) ?
			this.mergedBeanDefinitionHolders.computeIfAbsent(beanName,
					key -> new BeanDefinitionHolder(mbd, beanName, getAliases(bdName))) :
			new BeanDefinitionHolder(mbd, beanName, getAliases(bdName)));
	return resolver.isAutowireCandidate(holder, descriptor);
}

转化成通过注册的 ContextAnnotationAutowireCandidateResolver 来进行判断。

// QualifierAnnotationAutowireCandidateResolver
@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
	boolean match = super.isAutowireCandidate(bdHolder, descriptor);
	if (match) {
		// 检查 @Qualifier,不存在注解,直接返回 true
		match = checkQualifiers(bdHolder, descriptor.getAnnotations());
		if (match) {
			MethodParameter methodParam = descriptor.getMethodParameter();
			if (methodParam != null) {
				Method method = methodParam.getMethod();
				if (method == null || void.class == method.getReturnType()) {
					match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
				}
			}
		}
	}
	return match;
}
// GenericTypeAwareAutowireCandidateResolver
@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
	if (!super.isAutowireCandidate(bdHolder, descriptor)) {
		// If explicitly false, do not proceed with any other checks...
		return false;
	}
	return checkGenericTypeMatch(bdHolder, descriptor);
}
// SimpleAutowireCandidateResolver
@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
	return bdHolder.getBeanDefinition().isAutowireCandidate();
}
// AbstractBeanDefinition 默认 true
@Override
public boolean isAutowireCandidate() {
	return this.autowireCandidate;
}

在 BeanDefinition  的抽象实现 AbstractBeanDefinition 中,autowireCandidate 默认 true。所以最终的结果就是 checkGenericTypeMatch 方法的返回值。

protected boolean checkGenericTypeMatch(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
	// Field 定义类型或 @Bean 方法依赖的参数类型
	ResolvableType dependencyType = descriptor.getResolvableType();
	if (dependencyType.getType() instanceof Class) {
		// 没有泛型,不需要再次检查,直接返回
		return true;
	}

	ResolvableType targetType = null;
	boolean cacheType = false;
	RootBeanDefinition rbd = null;
	if (bdHolder.getBeanDefinition() instanceof RootBeanDefinition) {
		rbd = (RootBeanDefinition) bdHolder.getBeanDefinition();
	}
	if (rbd != null) {
		targetType = rbd.targetType;
		if (targetType == null) {
			cacheType = true;
			// 首先,检查工厂方法返回类型(如果适用)
			targetType = getReturnTypeForFactoryMethod(rbd, descriptor);
			if (targetType == null) {
				RootBeanDefinition dbd = getResolvedDecoratedDefinition(rbd);
				if (dbd != null) {
					targetType = dbd.targetType;
					if (targetType == null) {
						targetType = getReturnTypeForFactoryMethod(dbd, descriptor);
					}
				}
			}
		}
	}

	if (targetType == null) {
		// 常规情况:直接的bean实例,BeanFactory可用。
		if (this.beanFactory != null) {
			Class<?> beanType = this.beanFactory.getType(bdHolder.getBeanName());
			if (beanType != null) {
				targetType = ResolvableType.forClass(ClassUtils.getUserClass(beanType));
			}
		}
		// Fallback: no BeanFactory set, or no type resolvable through it
		// -> best-effort match against the target class if applicable.
		if (targetType == null && rbd != null && rbd.hasBeanClass() && rbd.getFactoryMethodName() == null) {
			Class<?> beanClass = rbd.getBeanClass();
			if (!FactoryBean.class.isAssignableFrom(beanClass)) {
				targetType = ResolvableType.forClass(ClassUtils.getUserClass(beanClass));
			}
		}
	}

	if (targetType == null) {
		return true;
	}
	if (cacheType) {
		rbd.targetType = targetType;
	}
	if (descriptor.fallbackMatchAllowed() &&
			(targetType.hasUnresolvableGenerics() || targetType.resolve() == Properties.class)) {
		// Fallback matches allow unresolvable generics, e.g. plain HashMap to Map<String,String>;
		// and pragmatically also java.util.Properties to any Map (since despite formally being a
		// Map<Object,Object>, java.util.Properties is usually perceived as a Map<String,String>).
		return true;
	}
	// 全面检查复杂泛型类型匹配
	return dependencyType.isAssignableFrom(targetType);
}

就是对泛型的匹配,没有泛型,直接返回 true。

// DefaultListableBeanFactory
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);
		}
	}
	// candidateName 对应的 bean 有可能已经创建了,那么此时放入的就是已经创建的实例 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 {
		// key  beanName
		// val  Class
		candidates.put(candidateName, getType(candidateName));
	}
}

public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
		throws BeansException {

	return beanFactory.getBean(beanName);
}

如果依赖的 beanName 对应的 bean 实例已经创建,则 candidates 中 value 值就是 bean 实例对象,没有创建,则 value 值为依赖的 Class 对象。

处理完 findAutowireCandidates,得到待注入的候选者 matchingBeans,为空直接返回,说明没有合适的候选者。否则,为 autowiredBeanName 和 instanceCandidate 赋值。instanceCandidate 若为 Class 类型,表明依赖的 bean 实例对象还未创建,调用 resolveCandidate 进行实例的创建。

这样,就完成了 spring 注解模式下对依赖的解析。

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潭影空人心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值