详解Spring的autowire-candidate设计

Xml配置文件中的default-autowire-candidates属性

有的同学对这个配置可能不熟悉或者说都不知道这个配置的存在,那首先我们看下default-autowire-candidates这个配置是放在何处的:

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
         default-autowire-candidates="service*">

    <bean id="serviceA" class="org.wonder.frame.xmlConfig.SetterBean$ServiceA" autowire-candidate="false"/>
    <bean id="serviceB" class="org.wonder.frame.xmlConfig.SetterBean$ServiceB"  />
    <bean id="setterBean" class="org.wonder.frame.xmlConfig.SetterBean" autowire="byType" />
</beans>

在idea中我们可以点开 default-autowire-candidates这个属性所在的spring-beans.xsd就能看到官方对这个属性的注释:

A default bean name pattern for identifying autowire candidates: e.g. "Service", "data", "Service", "dataService". Also accepts a comma-separated list of patterns: e.g. "Service,*Dao". See the documentation for the 'autowire-candidate' attribute of the 'bean' element for the semantic details of autowire candidate beans.

简单翻译下也就是说这个属性可以标示配置文件中的所有Bean默认能否成为自动注入候选者的名称匹配模式,比如 "Service", "data", "Service", "dataService".也支持以逗号分隔的字符串模式列表:"Service,Dao". 比如上面配置文件中配置的service就匹配了serviceA,serviceB两个Bean.但是Spring的设计规定serviceA自身配置的autowire-candidate为false会覆盖default-autowire-candidates配置,所以serviceA是不会成为自动注入的候选者。

匹配逻辑算法

我们深入到源码中看下Spring是如何根据这个匹配模式来与自身bean名称来匹配的

String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
   String candidatePattern = this.defaults.getAutowireCandidates();
   if (candidatePattern != null) {
      String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
      bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
   }
}
else {
   bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
}

很清楚,在bean本身配置autowire-candidate为空或者默认的情况下,Spring会把default-autowire-candidates字符串转换成数组,然后依赖PatternMatchUtils类的simpleMatch方法来验证当前bean的名称是否匹配,成功与否都会赋值给当前bean的autowireCandidate属性。其实最主要的还是PatternMatchUtils.simpleMatch方法

PatternMatchUtils.simpleMatch

public static boolean simpleMatch(@Nullable String pattern, @Nullable String str) {
   //pattern 匹配模式为空 或者待匹配字符串为空就返回false
   if (pattern == null || str == null) {
      return false;
   }
   //找到第一个* 在匹配模式字符串中的的索引
   int firstIndex = pattern.indexOf('*');
   if (firstIndex == -1) {
      //索引为空的情况下就代表 模式字符串要和待匹配字符串相等。
      return pattern.equals(str);
   }
   //*在第一位
   if (firstIndex == 0) {
      //*在第一位 且匹配模式字符串长度为1 那就直接返回true ,比如 *
      if (pattern.length() == 1) {
         return true;
      }
      //找到下一个*的起始位置
      int nextIndex = pattern.indexOf('*', firstIndex + 1);
      if (nextIndex == -1) {
         //如果没有*了,就判断 待匹配的字符串是否是以pattern结尾的。
         //比如*service   Aservice就满足这种情况
         return str.endsWith(pattern.substring(1));
      }
      //截取第一个* 和之后一个* 之间的字符串
      String part = pattern.substring(1, nextIndex);
      if (part.isEmpty()) {
         return simpleMatch(pattern.substring(nextIndex), str);
      }
      //str 是指待匹配的字符
      int partIndex = str.indexOf(part);
      while (partIndex != -1) {
         if (simpleMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length()))) {
            return true;
         }
         //从partIndex+1 开始计算part的索引
         partIndex = str.indexOf(part, partIndex + 1);
      }
      return false;
   }
   //待匹配字符串的长度比 第一个*的索引 大或者相等的情况下
   //截取模式字符串 0 到 第一个*号之间的字符串 ,截取 待匹配字符串 0 到 第一个*号之间的字符串 对比
   //如果相等 ,再截取 模式字符串  第一个*号之后的字符串 和 待匹配 字符串  第一个*号之后的字符串 去做匹配
   return (str.length() >= firstIndex &&
         pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex)) &&
         simpleMatch(pattern.substring(firstIndex), str.substring(firstIndex)));
}

这个Utils类的工具函数实现的字符串模糊匹配算法在我们日常开发中对字符串的操作方面也会有或多或少的帮助。

总结

Spring中的很多设计细节总是给我们很多惊喜,从中我们也可以很多小技巧,给我们日常开发会带来不少启发。

以上就是详解Spring的autowire-candidate设计的详细内容,更多关于Spring的autowire-candidate设计的资料请关注179885.Com其它相关文章!

猜你在找的详解Spring的autowire-candidate设计相关文章

Comparator比较器接口可以将自身传递给排序方法(比如Collections.sort或Arrays.sort),以便对排序顺序进行精确控制。本文讲述Spring中如何使用Comparator接口
今天给大家带来的是关于Java的相关知识,文章围绕着comparable和comparator的区别展开,文中有非常详细的介绍及代码示例,需求的大佬可以参考下
本文将向您展示如何使用Spring Boot创建一个的Spring Batch的Hello World示例。对和我一样入门的有一定的帮助,感兴趣的小伙伴们可以参考一下
了springboot+springsecurity如何实现动态url细粒度权限认证的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
Semaphore一般译作信号量,它也是一种线程同步工具,主要用于多个线程对共享资源进行并行操作的一种工具类。它代表了一种许可的概念,是否允许多线程对同一资源进行操
今天给大家带来的是关于Java的相关知识,文章围绕着Java常见的排序算法展开,文中有非常详细的介绍及代码示例,需求的大佬可以参考下
TCP是一种传输控制协议,是面向连接的、可靠的、基于字节流之间的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,TCP完成第四层传输层所指定的功
今天给大家带来的是关于Java的相关知识,文章围绕着Java如何实现树的同构展开,文中有非常详细的介绍及代码示例,需求的大佬可以参考下
本文主要介绍了MyBatis-Plus 使用枚举自动关联注入,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起
本文主要介绍了MyBatis-Plus通用枚举自动关联注入的实现,解决了繁琐的配置,让 mybatis 优雅的使用枚举属性,感兴趣的可以一起来了解一下
了SpringBoot集成Redis,并自定义对象序列化操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
为了方便邮件发送功能的使用,我们用邮件发送功能实现用户注册,实现步骤大概就是进行用户注册同时发送一封激活邮件,邮件里附带激活链接,关于Springboot发送邮件注册激