前言
关于AutowireCandidateResolver接口,可能绝大多数小伙伴都会觉得陌生。但若谈起@Autowired、@Primary、@Qualifier、@Value、@Lazy等注解,相信没有小伙伴是不知道的吧。
备注:@Primary这个注解是在解析bean定义时候处理的,解析成为isPrimary()从而在beanFactory里得到使用
在上篇文章:【小家Spring】使用@Async异步注解导致该Bean在循环依赖时启动报BeanCurrentlyInCreationException异常的根本原因分析,以及提供解决方案 有提到过可以使用@Autowired + @Lazy的方式来解决那个循环依赖问题,效果是它最终注入进去并不是容器内的代理对象(备注:是能够正常work的),有小伙伴有私聊我咋回事? 这篇文章中你可以找到答案~
AutowireCandidateResolver
用于确定特定的Bean定义是否符合特定的依赖项的候选者的策略接口。
这是这个接口类的Javadoc的描述,非常绕口、晦涩有木有???
此处我也先不要急着下定义了,毕竟我们的重点不是定义本身,而是现实。相信了解了它的工作原理,定义自在我心~
// @since 2.5 伴随着@Autowired体系出现 public interface AutowireCandidateResolver { // 判断给定的bean定义是否允许被依赖注入(bean定义的默认值都是true) default boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { return bdHolder.getBeanDefinition().isAutowireCandidate(); } // 给定的descriptor是否是必须的~~~ // @since 5.0 default boolean isRequired(DependencyDescriptor descriptor) { return descriptor.isRequired(); } // QualifierAnnotationAutowireCandidateResolver对它有实现 // @since 5.1 此方法出现得非常的晚 default boolean hasQualifier(DependencyDescriptor descriptor) { return false; } // 是否给一个建议值 注入的时候~~~QualifierAnnotationAutowireCandidateResolvert有实现 // @since 3.0 @Nullable default Object getSuggestedValue(DependencyDescriptor descriptor) { return null; } // 如果注入点injection point需要的话,就创建一个proxy来作为最终的解决方案ContextAnnotationAutowireCandidateResolver // @since 4.0 @Nullable default Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) { return null; } }
查看它的继承树:
层次特点非常明显:每一层都只有一个类,所以毫无疑问,最后一个实现类肯定是功能最全的了。
SimpleAutowireCandidateResolver
// @since 2.5 public class SimpleAutowireCandidateResolver implements AutowireCandidateResolver { @Override public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { return bdHolder.getBeanDefinition().isAutowireCandidate(); } @Override public boolean isRequired(DependencyDescriptor descriptor) { return descriptor.isRequired(); } @Override @Nullable public Object getSuggestedValue(DependencyDescriptor descriptor) { return null; } @Override @Nullable public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) { return null; } }
最简单的实现,适配器形式的存在,不可直接使用~
GenericTypeAwareAutowireCandidateResolver
从名字可以看出和泛型有关。Spring4.0
后的泛型依赖
注入主要是它来实现的,所以这个类也是Spring4.0
后出现的
//@since 4.0 它能够根据泛型类型进行匹配~~~~ 【泛型依赖注入】 public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCandidateResolver implements BeanFactoryAware { // 它能处理类型 毕竟@Autowired都是按照类型匹配的 @Nullable private BeanFactory beanFactory; // 是否允许被依赖~~~ // 因为bean定义里默认是true,绝大多数情况下我们不会修改它~~~ // 所以继续执行:checkGenericTypeMatch 看看泛型类型是否能够匹配上 // 若能够匹配上 这个就会被当作候选的Bean了~~~ @Override public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { // 如果bean定义里面已经不允许了 那就不往下走了 显然我们不会这么做 if (!super.isAutowireCandidate(bdHolder, descriptor)) { // If explicitly false, do not proceed with any other checks... return false; } // 处理泛型依赖的核心方法~~~ 也是本实现类的灵魂 // 注意:这里还兼容到了工厂方法模式FactoryMethod // 所以即使你返回BaseDao<T>它是能够很好的处理好类型的~~~ return checkGenericTypeMatch(bdHolder, descriptor); } ... }
本实现类的主要任务就是解决了泛型依赖,此类虽然为实现类,但也不建议直接使用,因为功能还不完整~
QualifierAnnotationAutowireCandidateResolver
这个实现类非常非常的重要,它继承自GenericTypeAwareAutowireCandidateResolver,所以它不仅仅能处理org.springframework.beans.factory.annotation.Qualifier、@Value,还能够处理泛型依赖注入,因此功能已经很完善了~~~ 在Spring2.5之后都使用它来处理依赖关系~
Spring4.0之前它继承自SimpleAutowireCandidateResolver,Spring4.0之后才继承自GenericTypeAwareAutowireCandidateResolver
它不仅仅能够处理@Qualifier注解,也能够处理通过@Value注解解析表达式得到的suggested value,也就是说它还实现了接口方法getSuggestedValue();
getSuggestedValue()方法是Spring3.0后提供的,因为@Value注解是Spring3.0后提供的强大注解。
关于@Value注解的魅力,请参阅:【小家Spring】Spring中@Value注解有多强大?从原理层面去剖析为何它有如此大的“能耐“
// @since 2.5 public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwareAutowireCandidateResolver { // 支持的注解类型,默认支持@Qualifier和JSR-330的javax.inject.Qualifier注解 private final Set<Class<? extends Annotation>> qualifierTypes = new LinkedHashSet<>(2); private Class<? extends Annotation> valueAnnotationType = Value.class; // 你可可以通过构造函数,增加你自定义的注解的支持~~~ // 注意都是add 不是set public QualifierAnnotationAutowireCandidateResolver(Class<? extends Annotation> qualifierType) { Assert.notNull(qualifierType, "'qualifierType' must not be null"); this.qualifierTypes.add(qualifierType); } public QualifierAnnotationAutowireCandidateResolver(Set<Class<? extends Annotation>> qualifierTypes) { Assert.notNull(qualifierTypes, "'qualifierTypes' must not be null"); this.qualifierTypes.addAll(qualifierTypes); } // 后面讲的CustomAutowireConfigurer 它会调用这个方法来自定义注解 public void addQualifierType(Class<? extends Annotation> qualifierType) { this.qualifierTypes.add(qualifierType); } //@Value注解类型Spring也是允许我们改成自己的类型的 public void setValueAnnotationType(Class<? extends Annotation> valueAnnotationType) { this.valueAnnotationType = valueAnnotationType; } // 这个实现,比父类的实现就更加的严格了,区分度也就越高了~~~ // checkQualifiers方法是本类的核心,灵魂 // 它有两个方法getQualifiedElementAnnotation和getFactoryMethodAnnotation表名了它支持filed和方法 @Override public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { boolean match = super.isAutowireCandidate(bdHolder, descriptor); // 这里发现,及时父类都匹配上了,我本来还得再次校验一把~~~ if (match) { // @Qualifier注解在此处生效 最终可能匹配出一个或者0个出来 match = checkQualifiers(bdHolder, descriptor.getAnnotations()); // 若字段上匹配上了还不行,还得看方法上的这个注解 if (match) { // 这里处理的是方法入参们~~~~ 只有方法有入参才需要继续解析 MethodParameter methodParam = descriptor.getMethodParameter(); if (methodParam != null) { Method method = methodParam.getMethod(); // 这个处理非常有意思:methodParam.getMethod()表示这个入参它所属于的方法 // 如果它不属于任何方法或者属于方法的返回值是void 才去看它头上标注的@Qualifier注解 if (method == null || void.class == method.getReturnType()) { match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations()); } } } } return match; } ... protected boolean isQualifier(Class<? extends Annotation> annotationType) { for (Class<? extends Annotation> qualifierType : this.qualifierTypes) { if (annotationType.equals(qualifierType) || annotationType.isAnnotationPresent(qualifierType)) { return true; } } return false; } // 这里显示的使用了Autowired 注解,我个人感觉这里是不应该的~~~~ 毕竟已经到这一步了 应该脱离@Autowired注解本身 // 当然,这里相当于是做了个fallback~~~还算可以接受吧 @Override public boolean isRequired(DependencyDescriptor descriptor) { if (!super.isRequired(descriptor)) { return false; } Autowired autowired = descriptor.getAnnotation(Autowired.class); return (autowired == null || autowired.required()); } // 标注的所有注解里 是否有@Qualifier这个注解~ @Override public boolean hasQualifier(DependencyDescriptor descriptor) { for (Annotation ann : descriptor.getAnnotations()) { if (isQualifier(ann.annotationType())) { return true; } } return false; } // @since 3.0 这是本类的另外一个核心 解析@Value注解 // 需要注意的是此类它不负责解析占位符啥的 只复杂把字符串返回 // 最终是交给value = evaluateBeanDefinitionString(strVal, bd);它处理~~~ @Override @Nullable public Object getSuggestedValue(DependencyDescriptor descriptor) { // 拿到value注解(当然不一定是@Value注解 可以自定义嘛) 并且拿到它的注解属性value值~~~ 比如#{person} Object value = findValue(descriptor.getAnnotations()); if (value == null) { // 相当于@Value注解标注在方法入参上 也是阔仪的~~~~~ MethodParameter methodParam = descriptor.getMethodParameter(); if (methodParam != null) { value = findValue(methodParam.getMethodAnnotations()); } } return value; } ... }
这个注解的功能已经非常强大了,Spring4.0
之前都是使用的它去解决候选、依赖问题,但也不建议直接使用,因为下面这个,也就是它的子类更为强大~