@Qualifier高级应用---按类别批量依赖注入(QualifierAnnotationAutowireCandidateResolver原理详解)【享学Spring】(中)

简介: @Qualifier高级应用---按类别批量依赖注入(QualifierAnnotationAutowireCandidateResolver原理详解)【享学Spring】(中)

它的fallback策略最多只能再向上再找一个层级(多了就不行了)。例如上例子中使用@B标注也是能起到@Qualifier效果的,但是若再加一个@C层级,限定符就不生效了。


注意:Class.isAnnotationPresent(Class<? extends Annotation> annotationClass)表示annotationClass是否标注在此类型上(此类型可以是任意Class类型)。

此方法不具有传递性:比如注解A上标注有@Qualifier,注解B上标注有@A注解,那么你用此方法判断@B上是否有@Qualifier它是返回false的(即使都写了@Inherited注解,因为和它没关系)


到这其实还是不能解释本文中为何@LoadBalanced参与了依赖注入,还得继续看精髓中的精髓checkQualifier()方法(方法名是单数,表示精确检查某一个单独的注解):


QualifierAnnotationAutowireCandidateResolver:
  // 检查某一个注解限定符,是否匹配当前的Bean
  protected boolean checkQualifier(BeanDefinitionHolder bdHolder, Annotation annotation, TypeConverter typeConverter) {
    // type:注解类型 bd:当前Bean的RootBeanDefinition 
    Class<? extends Annotation> type = annotation.annotationType();   
    RootBeanDefinition bd = (RootBeanDefinition) bdHolder.getBeanDefinition();
    // ========下面是匹配的关键步骤=========
    // 1、Bean定义信息的qualifiers字段一般都无值了(XML时代的配置除外)
    // 长名称不行再拿短名称去试了一把。显然此处 qualifier还是为null的
    AutowireCandidateQualifier qualifier = bd.getQualifier(type.getName());
    if (qualifier == null) {
      qualifier = bd.getQualifier(ClassUtils.getShortName(type));
    }
    //这里才是真真有料的地方~~~请认真看步骤
    if (qualifier == null) {
      // First, check annotation on qualified element, if any
      // 1、词方法是从bd标签里拿这个类型的注解声明,非XML配置时代此处targetAnnotation 为null
      Annotation targetAnnotation = getQualifiedElementAnnotation(bd, type);
      // Then, check annotation on factory method, if applicable
      // 2、若为null。去工厂方法里拿这个类型的注解。这方法里标注了两个注解@Bean和@LoadBalanced,所以此时targetAnnotation就不再为null了~~
      if (targetAnnotation == null) {
        targetAnnotation = getFactoryMethodAnnotation(bd, type);
      }
      // 若本类木有,还会去父类去找一趟
      if (targetAnnotation == null) {
        RootBeanDefinition dbd = getResolvedDecoratedDefinition(bd);
        if (dbd != null) {
          targetAnnotation = getFactoryMethodAnnotation(dbd, type);
        }
      }
      // 若xml、工厂方法、父里都还没找到此方法。那好家伙,回退到还去类本身上去看
      // 也就是说,如果@LoadBalanced标注在RestTemplate上,也是阔仪的
      if (targetAnnotation == null) {
        // Look for matching annotation on the target class
        ...
      }
      // 找到了,并且当且仅当就是这个注解的时候,就return true了~
      // Tips:这里使用的是equals,所以即使目标的和Bean都标注了@Qualifier属性,value值相同才行哟~~~~
      // 简单的说:只有value值相同,才会被选中的。否则这个Bean就是不符合条件的
      if (targetAnnotation != null && targetAnnotation.equals(annotation)) {
        return true;
      }
    }
    // 赞。若targetAnnotation还没找到,也就是还没匹配上。仍旧还不放弃,拿到当前这个注解的所有注解属性继续尝试匹配
    Map<String, Object> attributes = AnnotationUtils.getAnnotationAttributes(annotation);
    if (attributes.isEmpty() && qualifier == null) {
      return false;
    }
    ... // 详情不描述了。这就是为什么我们吧@Qualifier标注在某个类上面都能生效的原因 就是这里做了非常强大的兼容性~
  }
// =================它最重要的两个判断=================
if (targetAnnotation != null && targetAnnotation.equals(annotation));
// Fall back on bean name (or alias) match
if (actualValue == null && attributeName.equals(AutowireCandidateQualifier.VALUE_KEY) &&
          expectedValue instanceof String && bdHolder.matchesName((String) expectedValue));


checkQualifier()方法的实现,足以看到Spring作为一个优秀框架它对case的全面性,兼容性、灵活性的考虑还是很到位的。正因为Spring提供的强大的支持和灵活扩展,才给与了SpringBoot、SpringCloud在框架层面设计上更多可能性~





相关文章
|
12天前
|
人工智能 前端开发 Java
Spring AI Alibaba + 通义千问,开发AI应用如此简单!!!
本文介绍了如何使用Spring AI Alibaba开发一个简单的AI对话应用。通过引入`spring-ai-alibaba-starter`依赖和配置API密钥,结合Spring Boot项目,只需几行代码即可实现与AI模型的交互。具体步骤包括创建Spring Boot项目、编写Controller处理对话请求以及前端页面展示对话内容。此外,文章还介绍了如何通过添加对话记忆功能,使AI能够理解上下文并进行连贯对话。最后,总结了Spring AI为Java开发者带来的便利,简化了AI应用的开发流程。
201 0
|
12天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
18天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
68 14
|
1月前
|
XML Java 数据格式
Spring Core核心类库的功能与应用实践分析
【12月更文挑战第1天】大家好,今天我们来聊聊Spring Core这个强大的核心类库。Spring Core作为Spring框架的基础,提供了控制反转(IOC)和依赖注入(DI)等核心功能,以及企业级功能,如JNDI和定时任务等。通过本文,我们将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring Core,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
57 14
|
28天前
|
Java 数据库 数据安全/隐私保护
轻松掌握Spring依赖注入:打造你的登录验证系统
本文以轻松活泼的风格,带领读者走进Spring框架中的依赖注入和登录验证的世界。通过详细的步骤和代码示例,我们从DAO层的创建到Service层的实现,再到Spring配置文件的编写,最后通过测试类验证功能,一步步构建了一个简单的登录验证系统。文章不仅提供了实用的技术指导,还以口语化和生动的语言,让学习变得不再枯燥。
40 2
|
1月前
|
XML 前端开发 安全
Spring MVC:深入理解与应用实践
Spring MVC是Spring框架提供的一个用于构建Web应用程序的Model-View-Controller(MVC)实现。它通过分离业务逻辑、数据、显示来组织代码,使得Web应用程序的开发变得更加简洁和高效。本文将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring MVC,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
67 2
|
2月前
|
JSON 安全 算法
Spring Boot 应用如何实现 JWT 认证?
Spring Boot 应用如何实现 JWT 认证?
79 8
|
2月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
2月前
|
消息中间件 Java Kafka
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
57 1
|
2月前
|
Java Docker 微服务
利用Docker容器化部署Spring Boot应用
利用Docker容器化部署Spring Boot应用
54 0