当前已经解析过的依赖截图如下:这些特殊类型,可以直接@Autowired注入
上面代码的处理过程总结如下:
1.Spring注入依赖后会保存依赖的beanName,作为下次注入相同属性的捷径。如果存在捷径的话,直接通过保存的beanName获取bean实例
2.对@Value注解的处理。如果存在,会获取并解析value值
3.对数组或容器类型的处理。如果是数组或容器类型的话,Spring可以将所有与目标类型匹配的bean实例都注入进去,不需要判断
1.获取数组或容器单个组件的类型
2.调用findAutowireCandidates方法,获取与组件类型匹配的Map(beanName -> bean实例)
3.保存类型匹配的beanNames
4.非数组、容器类型的处理
1.调用findAutowireCandidates方法,获取与组件类型匹配的Map(beanName -> bean实例)
2.如果类型匹配的结果为多个,需要进行筛选(@Primary、优先级、字段名)
3.如果筛选结果不为空,或者只有一个bean类型匹配,就直接使用该bean
DefaultListableBeanFactory#findAutowireCandidates:搜索类型匹配的beand的Map
根据注解进行依赖注入的主要工作,就是根据标注的字段的类型来搜索符合的bean,并将类型匹配的bean注入到字段中。而搜索bean的工作在这个方法中实现:
protected Map<String, Object> findAutowireCandidates( @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) { // 获取类型匹配的bean的beanName列表(包括父容器,但是此时还没有进行泛型的精确匹配) String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this, requiredType, true, descriptor.isEager()); //存放结果的Map(beanName -> bena实例) 最终会return的 Map<String, Object> result = new LinkedHashMap<>(candidateNames.length); //如果注入类型是特殊类型或其子类,会将特殊类型的实例添加到结果 // 哪些特殊类型呢?上面截图有,比如你要注入ApplicationContext、BeanFactory等等 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; } } } // candidateNames可能会有多个,这里就要开始过滤了,比如@Qualifier、泛型等等 for (String candidate : candidateNames) { //不是自引用 && 符合注入条件 // 自引用的判断:找到的候选的Bean的名称和当前Bean名称相等 或者 当前bean名称等于工厂bean的名称~~~~~~~ // isAutowireCandidate:这个方法非常的关键,判断该bean是否允许注入进来。泛型的匹配就发生在这个方法里,下面会详解 if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } 结果集为空 && 注入属性是非数组、容器类型 那么Spring就会放宽注入条件,然后继续寻找 // 什么叫放宽:比如泛型不要求精确匹配了、比如自引用的注入等等 if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) { // Consider fallback matches if the first pass failed to find anything... FallbackMatch:放宽对泛型类型的验证 所以从这里用了一个新的fallbackDescriptor 对象 相当于放宽了泛型的匹配 DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch(); for (String candidate : candidateNames) { if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } if (result.isEmpty()) { // Consider self references as a final pass... // but in the case of a dependency collection, not the very same bean itself. 如果结果还是为空,Spring会将自引用添加到结果中 自引用是放在最后一步添加进去的 for (String candidate : candidateNames) { if (isSelfReference(beanName, candidate) && (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) && isAutowireCandidate(candidate, fallbackDescriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } } } return result; }
步骤总结:
1.将获取类型匹配的Bean工作交给BeanFactoryUtils.beanNamesForTypeIncludingAncestors。该方法除了当前beanFactory还会递归对父parentFactory进行查找
2.如果注入类型是特殊类型或其子类,会将特殊类型的实例添加到结果
3.对结果进行筛选
1.BeanDefinition的autowireCandidate属性,表示是否允许该bena注入到其他bean中,默认为true
2.泛型类型的匹配,如果存在的话
3.Qualifier注解。如果存在Qualifier注解的话,会直接比对Qualifier注解中指定的beanName。需要注意的是,Spring处理自己定义的Qualifier注解,还支持javax.inject.Qualifier注解
4.如果筛选后,结果为空,Spring会放宽筛选条件,再筛选一次
DefaultListableBeanFactory#isAutowireCandidate 判断指定的descriptor是否能够被注入
Determine whether the specified bean definition qualifies as an autowire candidate to be injected into other beans which declare a dependency of matching type.
@Override public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException { //getAutowireCandidateResolver()为ContextAnnotationAutowireCandidateResolver return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver()); } protected boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver) throws NoSuchBeanDefinitionException { String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName); // 若存在Bean定义,就走这里(因为有的Bean可能是直接registerSingleton进来的,是不存在Bean定义的) // 我们的注入,绝大部分情况都走这里 if (containsBeanDefinition(beanDefinitionName)) { //getMergedLocalBeanDefinition方法的作用就是获取缓存的BeanDefinition对象并合并其父类和本身的属性 return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanDefinitionName), descriptor, resolver); } // 若已经存在实例了,就走这里 else if (containsSingleton(beanName)) { return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver); } // 父容器 有可能为null,为null就肯定走else默认值了 true 可以注入 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); } // 默认值是true else { return true; } } protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd, DependencyDescriptor descriptor, AutowireCandidateResolver resolver) { String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName); //resolveBeanClass 这个方法之前提到过,主要是保证此Class已经被加载进来了 resolveBeanClass(mbd, beanDefinitionName); //是否已经指定引用非重载方法的工厂方法名。 默认值是true if (mbd.isFactoryMethodUnique) { boolean resolve; synchronized (mbd.constructorArgumentLock) { resolve = (mbd.resolvedConstructorOrFactoryMethod == null); } // 此处主要处理工厂方法的方式,此处先略过~ if (resolve) { new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd); } } // 核心来了。ContextAnnotationAutowireCandidateResolver#isAutowireCandidate方法 // 真正的实现在父类:QualifierAnnotationAutowireCandidateResolver它身上 return resolver.isAutowireCandidate( new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), descriptor); }
QualifierAnnotationAutowireCandidateResolver#isAutowireCandidate
:判断该Bean是否能注入(会解析@Qualifier注解)
@Override public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { boolean match = super.isAutowireCandidate(bdHolder, descriptor); // 到了这,如果是false,说明泛型没有匹配上(那就不用继续往下走了) // 如果是true,那就继续,解析@Qualifier注解啦 所以若你标记了@Qualifier注解 也是需要对应上 if (match) { // 这个逻辑比较简单,看看有没有标注@Qualifier注解(没有标注也是返回true~~) // 需要注意的是,Spring这里支持自己的@Qualifier,也支持javax.inject.Qualifier // checkQualifiers() 这个方法有一些有意思的处理,因此还是决定讲解一下,请参见下面的解析~~~~~ 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; } //boolean match = super.isAutowireCandidate(bdHolder, descriptor);(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; } // 这里,这里,这里 看方法名就能看出来。检测看看泛型是否匹配。 // 若泛型都不匹配,就直接返回false了,基本步骤为: //1、从descriptor里拿倒泛型类型 //2、First, check factory method return type, if applicable //3、return dependencyType.isAssignableFrom(targetType); // 这个方法官方doc为:Full check for complex generic type match... 带泛型的全检查,而不是简单Class类型的判断 return checkGenericTypeMatch(bdHolder, descriptor); } // if (!super.isAutowireCandidate(bdHolder, descriptor)) { (SimpleAutowireCandidateResolver中) @Override public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { // Bean定义信息的默认值,都会返回true return bdHolder.getBeanDefinition().isAutowireCandidate(); }
QualifierAnnotationAutowireCandidateResolver#checkQualifiers:检查@Qualifier注解是否符合条件
上面知道了,若类型啥的都匹配上了,接下来还得解析@Qualifier是否匹配,它有一个很有意思的点:@Qualifier可以标注在类上面,也可以达到匹配的效果。(但它不是Bean名称,也不是bean的别名)
/** * Match the given qualifier annotations against the candidate bean definition. * 将给定的@Qualifier注解与候选bean定义匹配~~~(简单的书就是看看类型已匹配上的,@Qualifier是否还能匹配上) */ protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) { // 这里一般会有两个注解 一个@Autowired 一个@Qualifier // 或者还有其余的组合注解~~~ if (ObjectUtils.isEmpty(annotationsToSearch)) { return true; } SimpleTypeConverter typeConverter = new SimpleTypeConverter(); for (Annotation annotation : annotationsToSearch) { Class<? extends Annotation> type = annotation.annotationType(); boolean checkMeta = true; boolean fallbackToMeta = false; //isQualifier:判断是不是@Qualifier注解以及 JSR330的`javax.inject.Qualifier`注解也是支持的 if (isQualifier(type)) { // checkQualifier 最重要的方法就是这个了,它是个重载方法。。。它的内容非常长,大致我在这里解析步骤如下: //1、bd.getQualifier 看看Bean定义里是否已经定义过tQualifier们(但是经过我的跟踪,Bean定义得这个字段:private final Map<String, AutowireCandidateQualifier> qualifiers;永远不会被赋值 如有人知道,请告知我 了能事Spring预留得吧) //2、该Bean定义得AnnotatedElement qualifiedElement的这个属性上是否有指定的注解,有就拿出这个Annotation,否则继续下一步 //3、resolvedFactoryMethod工厂方法上是否有这个注解,否则进行下一步(下一步事关键。。。) //4、Look for matching annotation on the target class JavaDoc得意思备注也很清晰,就是去具体得类上面,看有没有有对应的注解,有就拿出来。 //(有个细节):即使这个类被代理了,也是能拿到标注在它上面的注解的 因为: AnnotationUtils.getAnnotation(ClassUtils.getUserClass(bd.getBeanClass()), type) //5、到这里,如国获得了对应的@Qualifier注解,那就会比较。如果value值也相同,那就return true,否则继续往下走 //6、接下来拿到这个注解的attributes,然后判断若@Qualifier没有value值或者是空串,就只return false了 否则继续看 //7、最终会和Bean上面那个注解(一般都是@Component等注解)的value值和@Qualifier得value值进行比较,若相等 就最终返回true勒(请注意:此处Bean得alias别名若相等也是会返回true) //8、======就这样,我们就完成了Bean定义和@Qualifier得一个匹配过程====== if (!checkQualifier(bdHolder, annotation, typeConverter)) { fallbackToMeta = true; } else { checkMeta = false; } } // 这一步非常有效:相当于支持到了组合注解的情况。 它连注解的注解都会解析 // 比如我们@MyAnno上面还有@Qualifier注解,仍然会被这里解析到的 内部有一个递归 if (checkMeta) { boolean foundMeta = false; for (Annotation metaAnn : type.getAnnotations()) { Class<? extends Annotation> metaType = metaAnn.annotationType(); if (isQualifier(metaType)) { foundMeta = true; // Only accept fallback match if @Qualifier annotation has a value... // Otherwise it is just a marker for a custom qualifier annotation. if ((fallbackToMeta && StringUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) || !checkQualifier(bdHolder, metaAnn, typeConverter)) { return false; } } } if (fallbackToMeta && !foundMeta) { return false; } } } return true; }
当我们注入GenericBean<Object, Object>
,DependencyDescriptor descriptor
参考如下:
我们发现它的类型都是带有泛型的