Spring Boot源码简析 @Qualifier

源码

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
	String value() default "";
}

@Inherited表示支持被继承;

简析

org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver实现了依赖注入候选解析器接口org.springframework.beans.factory.support.AutowireCandidateResolver,继承自org.springframework.beans.factory.support.GenericTypeAwareAutowireCandidateResolver,Spring默认使用它负责候选处理,专门用于解析
org.springframework.beans.factory.annotation.Qualifier注解;

构造函数

public QualifierAnnotationAutowireCandidateResolver() {
    // 默认支持@Qualifier和javax.inject.Qualifier
    this.qualifierTypes.add(Qualifier.class);
    try {
        this.qualifierTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Qualifier",
                        QualifierAnnotationAutowireCandidateResolver.class.getClassLoader()));
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

核心方法

/**
 * bdHolder 候选Bean的定义信息
 * descriptor 待自动注入的描述信息
 */
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    // 先经过父类判断,是否允许依赖注入、泛型匹配
    boolean match = super.isAutowireCandidate(bdHolder, descriptor);
    if (match) {
        // 满足父类要求后,再进行判断@Qualifier注解是否匹配
        // 如果descriptor是Field,则获取Field上的注解
        // 如果descriptor是MethodParameter,则获取方法参数上的注解
        match = checkQualifiers(bdHolder, descriptor.getAnnotations());
        if (match) {
            // 若是MethodParameter,则需要进一步判断方法参数所在方法上的@Qualifier注解是否匹配
            MethodParameter methodParam = descriptor.getMethodParameter();
            if (methodParam != null) {
                Method method = methodParam.getMethod();
                if (method == null || void.class == method.getReturnType()) {
                    // 进一步校验构造函数/void方法上@Qualifier注解是否匹配
                    match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
                }
            }
        }
    }
    return match;
}

protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) {
    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;
        // 判断当前注解是否是@Qualifier注解
        if (isQualifier(type)) {
            // 判断当前Bean是否匹配@Qualifier注解
            if (!checkQualifier(bdHolder, annotation, typeConverter)) {
                // 未匹配,则进一步尝试校验其元注解
                fallbackToMeta = true;
            }
            else {
                // 匹配,则无需校验元注解
                checkMeta = false;
            }
        }
        // 匹配失败,或者不是@Qualifier注解,则需要校验元注解
        if (checkMeta) {
            boolean foundMeta = false;
            // 遍历当前注解的元注解列表
            for (Annotation metaAnn : type.getAnnotations()) {
                Class<? extends Annotation> metaType = metaAnn.annotationType();
                // 校验当前元注解是否是@Qualifier注解
                if (isQualifier(metaType)) {
                    // 存在@Qualifier元注解
                    foundMeta = true;
                    // 如果fallbackToMeta,说明当前@Qualifier注解匹配失败,且存在@Qualifier元注解
                    // 那么@Qualifier元注解必须有值可以进行后续校验,否则认为不匹配
                    // Only accept fallback match if @Qualifier annotation has a value...
                    // 或者@A标注了@Qualifier,@B标注了@A,当annotation为@B时,fallbackToMeta为false,此时进一步判断当前Bean是否匹配@A注解
                    // 只向上找一层,如果@C标注了@B,当annotation为@C时,则无法fallbackToMeta
                    // Otherwise it is just a marker for a custom qualifier annotation.
                    if ((fallbackToMeta && ObjectUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
                        !checkQualifier(bdHolder, metaAnn, typeConverter)) {
                        // 不满足以上条件,则认为不匹配
                        return false;
                    }
                }
            }
            if (fallbackToMeta && !foundMeta) {
                // 如果fallbackToMeta且未找到匹配的元注解,则认为不匹配
                return false;
            }
        }
    }
    // 成功遍历完待校验注解列表,则认为匹配成功
    return true;
}

protected boolean isQualifier(Class<? extends Annotation> annotationType) {
    // 遍历已注册的Qualifier注解
    for (Class<? extends Annotation> qualifierType : this.qualifierTypes) {
        // 待判断的注解匹配当前注解类型或者标注了当前注解,则认为属于Qualifier注解
        if (annotationType.equals(qualifierType) || annotationType.isAnnotationPresent(qualifierType)) {
            return true;
        }
    }
    return false;
}

protected boolean checkQualifier(
        BeanDefinitionHolder bdHolder, Annotation annotation, TypeConverter typeConverter) {

    Class<? extends Annotation> type = annotation.annotationType();
    RootBeanDefinition bd = (RootBeanDefinition) bdHolder.getBeanDefinition();

    // Bean定义信息的qualifiers字段一般都为空
    AutowireCandidateQualifier qualifier = bd.getQualifier(type.getName());
    if (qualifier == null) {
        qualifier = bd.getQualifier(ClassUtils.getShortName(type));
    }
    // 优先使用qualifier(xml配置),若qualifier为空则尝试获取targetAnnotation
    // 
    //     
    // 
    if (qualifier == null) {
        // 尝试从Bean定义信息获取该类型的注解信息
        // First, check annotation on qualified element, if any
        Annotation targetAnnotation = getQualifiedElementAnnotation(bd, type);
        // Then, check annotation on factory method, if applicable
        if (targetAnnotation == null) {
            // 若注解信息不存在,则尝试从Bean的工厂方法中获取该类型的注解信息
            targetAnnotation = getFactoryMethodAnnotation(bd, type);
        }
        if (targetAnnotation == null) {
            RootBeanDefinition dbd = getResolvedDecoratedDefinition(bd);
            if (dbd != null) {
                targetAnnotation = getFactoryMethodAnnotation(dbd, type);
            }
        }
        if (targetAnnotation == null) {
            // 若注解信息不存在,则从本类上获取该类型的注解信息
            // Look for matching annotation on the target class
            if (getBeanFactory() != null) {
                try {
                    Class<?> beanType = getBeanFactory().getType(bdHolder.getBeanName());
                    if (beanType != null) {
                        targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(beanType), type);
                    }
                }
                catch (NoSuchBeanDefinitionException ex) {
                    // Not the usual case - simply forget about the type check...
                }
            }
            if (targetAnnotation == null && bd.hasBeanClass()) {
                targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(bd.getBeanClass()), type);
            }
        }
        // 注解存在,且匹配待校验注解,则认为匹配
        if (targetAnnotation != null && targetAnnotation.equals(annotation)) {
            return true;
        }
    }

    // 若注解不存在,或者未匹配,则匹配待校验注解的所有属性
    Map<String, Object> attributes = AnnotationUtils.getAnnotationAttributes(annotation);
    if (attributes.isEmpty() && qualifier == null) {
        // 待校验注解不存在属性,则认为不匹配,因为注解不存在
        // If no attributes, the qualifier must be present
        return false;
    }
    // 遍历待校验注解的属性
    // @Qualifier注解只有value属性
    // 但是标注了@Qualifier注解的自定义注解,可以拥有其它属性
    for (Map.Entry<String, Object> entry : attributes.entrySet()) {
        // 属性名称
        String attributeName = entry.getKey();
        // 期望的属性值
        Object expectedValue = entry.getValue();
        Object actualValue = null;
        // Check qualifier first
        if (qualifier != null) {
            // 从qualifier中获取属性值,若存在的话
            actualValue = qualifier.getAttribute(attributeName);
        }
        if (actualValue == null) {
            // 从Bean定义信息中获取属性值
            // Fall back on bean definition attribute
            actualValue = bd.getAttribute(attributeName);
        }
        if (actualValue == null && attributeName.equals(AutowireCandidateQualifier.VALUE_KEY) &&
            expectedValue instanceof String && bdHolder.matchesName((String) expectedValue)) {
            // 若属性值不存在,则判断Bean的名称是否匹配属性value对应的值
            // Fall back on bean name (or alias) match
            continue;
        }
        if (actualValue == null && qualifier != null) {
            // Fall back on default, but only if the qualifier is present
            actualValue = AnnotationUtils.getDefaultValue(annotation, attributeName);
        }
        if (actualValue != null) {
            actualValue = typeConverter.convertIfNecessary(actualValue, expectedValue.getClass());
        }
        if (!expectedValue.equals(actualValue)) {
            return false;
        }
    }
    // 成功遍历玩待校验注解的所有属性,则认为匹配成功
    return true;
}

应用

过滤多匹配值

@Configuration
public class DemoConfiguration {

    // 过滤demo类别
    @Qualifier(value = "demo")
    @Autowired
    private Demo demo;

    // 默认demo类别
    @Bean
    public Demo demo() {
        return new Demo("demo");
    }

    // 默认demo1类别
    @Bean
    public Demo demo1() {
        return new Demo("demo1");
    }

    // 指定类别为为demo1
    @Qualifier(value = "demo1")
    @Bean
    public Demo demo2() {
        return new Demo("demo2");
    }

    static class Demo {
        private String name;

        public Demo(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Demo{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(DemoConfiguration.class);
        DemoConfiguration bean = context.getBean(DemoConfiguration.class);
        System.out.println(bean.demo);
    }
}

指定类别过滤

@Configuration
public class DemoConfiguration {

    // 过滤demo类别
    @Qualifier(value = "demo")
    @Autowired
    private List<Demo> demos;

    // 满足 (actualValue == null && 
    // attributeName.equals(AutowireCandidateQualifier.VALUE_KEY) && 
    // expectedValue instanceof String && 
    // bdHolder.matchesName((String) expectedValue))
    @Bean
    public Demo demo() {
        return new Demo("demo");
    }
    
    // 满足 (targetAnnotation != null && targetAnnotation.equals(annotation))
    // 指定类别为demo
    @Qualifier(value = "demo")
    @Bean
    public Demo demo1() {
        return new Demo("demo1");
    }

    // 默认demo2类别
    @Bean
    public Demo demo2() {
        return new Demo("demo2");
    }

    static class Demo {
        private String name;

        public Demo(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Demo{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(DemoConfiguration.class);
        DemoConfiguration bean = context.getBean(DemoConfiguration.class);
        System.out.println(bean.demos);
    }
}

自定义类别注解过滤

@Configuration
public class DemoConfiguration {

    // 过滤@DemoTag注解
    @DemoTag
    @Autowired
    private List<Demo> demos;

    @Bean
    public Demo demo() {
        return new Demo("demo");
    }

    // 指定@DemoTag注解
    @DemoTag
    @Bean
    public Demo demo1() {
        return new Demo("demo1");
    }

    // 指定@DemoTag注解
    @DemoTag
    @Bean
    public Demo demo2() {
        return new Demo("demo2");
    }

    static class Demo {
        private String name;

        public Demo(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Demo{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }

    @Target({ElementType.FIELD, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Qualifier
    @interface DemoTag {
    }

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(DemoConfiguration.class);
        DemoConfiguration bean = context.getBean(DemoConfiguration.class);
        System.out.println(bean.demos);
    }
}

你可能感兴趣的:(Spring,Boot,spring,boot)