概述
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,这个时候下面的判断不满足,于是就不会返回,继续执行下一个后置处理器AutowiredAnnotationBeanPostProcessor
的predictBeanType
方法,具体的代码如下:
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
的注解是先根据类型找,然后如果类型找不到再根据名字找,那么从源码的角度来说,是不是对的呢?想必读者看了这篇博客已经有了答案。
最后
以上就是跳跃大神为你收集整理的Spring源码系列(十九)Autowired注解的查找规则的全部内容,希望文章能够帮你解决Spring源码系列(十九)Autowired注解的查找规则所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复