@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在框架层面设计上更多可能性~





相关文章
|
26天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
130 1
|
10天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
88 62
|
7天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
8天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
21 2
|
21天前
|
人工智能 开发框架 Java
总计 30 万奖金,Spring AI Alibaba 应用框架挑战赛开赛
Spring AI Alibaba 应用框架挑战赛邀请广大开发者参与开源项目的共建,助力项目快速发展,掌握 AI 应用开发模式。大赛分为《支持 Spring AI Alibaba 应用可视化调试与追踪本地工具》和《基于 Flow 的 AI 编排机制设计与实现》两个赛道,总计 30 万奖金。
|
27天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第8天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建并配置 Spring Boot 项目,实现后端 API 和安全配置。接着,使用 Ant Design Pro Vue 脚手架创建前端项目,配置动态路由和菜单,并创建相应的页面组件。最后,通过具体实践心得,分享了版本兼容性、安全性、性能调优等注意事项,帮助读者快速搭建高效且易维护的应用框架。
38 3
|
27天前
|
Java Spring 容器
Spring底层原理大致脉络
Spring底层原理大致脉络
|
28天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第7天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建 Spring Boot 项目并配置 Spring Security。接着,实现后端 API 以提供菜单数据。在前端部分,使用 Ant Design Pro Vue 脚手架创建项目,并配置动态路由和菜单。最后,启动前后端服务,实现高效、美观且功能强大的应用框架。
34 2
|
15天前
|
存储 Java 数据管理
强大!用 @Audited 注解增强 Spring Boot 应用,打造健壮的数据审计功能
本文深入介绍了如何在Spring Boot应用中使用`@Audited`注解和`spring-data-envers`实现数据审计功能,涵盖从添加依赖、配置实体类到查询审计数据的具体步骤,助力开发人员构建更加透明、合规的应用系统。
|
22天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
53 0