详解Spring的autowire-candidate设计

目录
  • Xml配置文件中的default-autowire-candidates属性
  • 匹配逻辑算法
    • PatternMatchUtils.simpleMatch
  • 总结

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设计的资料请关注我们其它相关文章!

(0)

相关推荐

  • Spring Batch 入门示例

    目录 1.Spring Batch框架工作原理 2.示例概述 3. Maven配置 4. Spring Boot 配置 5. 创建实体模型 6. 配置 Spring Batch Job 7. 处理数据 8.测试Spring Batch 示例 我将向您展示如何使用Spring Boot创建一个的Spring Batch的Hello World示例. (循序渐进) 因此,如果您是Spring Batch的初学者,您一定会喜欢本指南. 准备好了吗? 如果您想了解更多关于Spring Batch的信息,

  • 详解SpringBoot异常处理流程及原理

    异常处理流程 执行目标方法,目标方法运行期间有任何异常都会被catch捕获,并标志当前请求结束,dispatchException抛出异常 进入视图解析流程,并渲染页面,发生异常时,参数mv为空,传入捕获的异常dispatchException 处理handler发生的异常,处理完成返回ModelAndView (1)遍历所有的HandlerExceptionResolvers,找到可以处理当前异常的解析器来解析异常 (2)调用resolveException解析异常,传入request和res

  • SpringAop日志找不到方法的处理

    SpringAop日志找不到方法 错误截图: 显示没有找到该方法,于是我找到对应的类和对应的方法: 这里我用了反射来获取方法名和参数: 错误打印的结果显示方法名获取没有错误,于是我查看参数的类型是否有错 结果一个都对不上- int类型反射得到的class: Integer反射得到的Class: -终于知道之前错误里的Ljavexxxx是哪里来的了- 由于model是一个接口 model反射的Class得到的是他的子类org.springframework.validation.support.B

  • spring 中事务注解@Transactional与trycatch的使用

    spring事务注解@Transactional与trycatch 在项目中 @service层中 我们会经常在做一些增删改操作的方法上看到 spring 的事务注解 @transaction 已知@transaction 是让spring 帮我们实现事务的控制. 但是在项目中会经常看到 有的方法中 会存在trycatch块包括的方法上注解着@transaction eg: @Override @Transactional public Json addOrder(TOrderAddReq tO

  • Spring中如何使用Comparator接口

    我们先来回顾下Comparator接口在我们日常开发中的作用,Comparator比较器接口可以将自身传递给排序方法(比如Collections.sort或Arrays.sort),以便对排序顺序进行精确控制.比如: List<Integer> intList = Arrays.asList(2, 3, 1); Collections.sort(intList, (o1, o2) -> { return o2-o1; }); 输出 [3, 2, 1] Comparator可以用来控制某些

  • SpringCloud Alibaba项目实战之nacos-server服务搭建过程

    目录 1.Nacos简介 1.1.什么是Nacos 1.2.Nacos基本原理 2.Nacos-Server服务部署 2.1.standalone 模式 2.2.cluster 模式 源码地址:https://gitee.com/fighter3/eshop-project.git 持续更新中-- 大家好,我是三分恶. 这一节我们来学习SpringCloud Alibaba体系中一个非常重要的组件--Nacos. 1.Nacos简介 Nacos官方网站:https://nacos.io/zh-c

  • 浅谈什么是SpringBoot异常处理自动配置的原理

    异常处理自动配置 ErrorMvcAutoConfiguration自动配置类自动配置了处理规则,给容器中注册了多种组件 errorAttributes组件,类型为DefaultErrorAttributes.这个组件定义错误页面中可以包含哪些数据 basicErrorController组件,类型为BasicErrorController.处理默认/error路径的请求,new一个id为error的ModelAndView对象来响应页面 error组件,类型为View.响应的是默认错误页面 b

  • Spring中的AutowireCandidateResolver的具体使用详解

    接口定义 用于推断一个特定的beanDefinition是否能作为指定依赖的候选者的策略接口 public interface AutowireCandidateResolver { // 默认情况下直接根据bd中的定义返回,如果没有进行特殊配置的话为true default boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { return bdHolder.g

  • 详解Spring的autowire-candidate设计

    目录 Xml配置文件中的default-autowire-candidates属性 匹配逻辑算法 PatternMatchUtils.simpleMatch 总结 Xml配置文件中的default-autowire-candidates属性 有的同学对这个配置可能不熟悉或者说都不知道这个配置的存在,那首先我们看下default-autowire-candidates这个配置是放在何处的: <beans xmlns="http://www.springframework.org/schema

  • 详解Spring data 定义默认时间与日期的实例

    详解Spring data 定义默认时间与日期的实例 前言: 需求是这样的: 1. 创建时间与更新时间只能由数据库产生,不允许在实体类中产生,因为每个节点的时间/时区不一定一直.另外防止人为插入自定义时间时间. 2. 插入记录的时候创建默认时间,创建时间不能为空,时间一旦插入不允许日后在实体类中修改. 3. 记录创建后更新日志字段为默认为 null 表示该记录没有被修改过.一旦数据被修改,修改日期字段将记录下最后的修改时间. 4. 甚至你可以通过触发器实现一个history 表,用来记录数据的历

  • 详解Spring工厂特性

    一.饿汉式创建优势 工厂创建之后,会将Spring配置文件中的所有对象都创建完成(饿汉式). 提高程序运行效率.避免多次IO,减少对象创建时间.(概念接近连接池,一次性创建好,使用时直接获取) 二.生命周期方法 自定义初始化方法:添加"init-method"属性,Spring则会在创建对象之后,调用此方法. 自定义销毁方法:添加"destroy-method"属性,Spring则会在销毁对象之前,调用此方法. 销毁:工厂的close()方法被调用之后,Spring

  • 详解Spring不同数据库异常如何抽象的

    目录 前言 代码实现 处理流程图 用到了哪些设计模式? 组合模式 单例模式 策略模式 总结: 前言 使用Spring-Jdbc的情况下,在有些场景中,我们需要根据数据库报的异常类型的不同,来编写我们的业务代码.比如说,我们有这样一段逻辑,如果我们新插入的记录,存在唯一约束冲突,就会返回给客户端描述:记录已存在,请勿重复操作 代码一般是这么写的: @Resource private JdbcTemplate jdbcTemplate; public String testAdd(){ try {

  • 详解Spring中的Environment外部化配置管理

    目录 profiles ProfileService 声明一个配置类 定义测试方法 profiles总结 Properties environment的应用 指定profile属性 @Value注解的使用 SpringEnvironment原理设计 Environment的中文意思是环境,它表示整个spring应用运行时的环境信息,它包含两个关键因素 profiles properties profiles profiles这个概念相信大家都已经理解了,最常见的就是不同环境下,决定当前sprin

  • 详解Spring中Lookup注解的使用

    我们知道在spring容器中单独的一个抽象类是不能成为一个bean的,那么有没有办法呢?这个时候我们可以使用Lookup注解,我们可以看下spring的扫描bean部分逻辑.我们知道在spring中要想成为一个bean,必须先生成BeanDefinition对象,如果一个抽象类中没有含有Lookup注解的方法,在spring扫描时就会被排除掉. /** * 1.判断是不是独立的类,非静态内部类则无法生成bean, * 2.判断是不是接口或者抽象类(有一种特殊情况),是则无法生成 * 3.判断如果

  • 详解Spring Security中权限注解的使用

    目录 1. 具体用法 2. SpEL 3. @PreAuthorize 最近有个小伙伴在微信群里问 Spring Security 权限注解的问题: 很多时候事情就是这么巧,松哥最近在做的 tienchin 也是基于注解来处理权限问题的,所以既然大家有这个问题,咱们就一块来聊聊这个话题. 当然一些基础的知识我就不讲了,对于 Spring Security 基本用法尚不熟悉的小伙伴,可在公众号后台回复 ss,有原创的系列教程. 1. 具体用法 先来看看 Spring Security 权限注解的具

  • 详解Spring Bean的集合注入和自动装配

    目录 一.Spring Bean 集合注入 集合常用标签 案例 二.Spring Bean自动装配 什么是自动装配 自动装配的方式 案例 注意点 一.Spring Bean 集合注入 在[Spring学习笔记(三)]已经讲了怎么注入基本数据类型和引用数据类型,接下来介绍如何注入比较特殊的数据类型——集合 集合常用标签 集合注入,用法也很简单,只需要在 Bean 标签下的 <property> 或<constructor-arg>元素中添加以下集合的标签,再通过value或者ref进

  • 详解Spring Security如何在权限中使用通配符

    目录 前言 1. SpEL 2. 自定义权限该如何写 3. 权限通配符 4. TienChin 项目怎么做的 前言 小伙伴们知道,在 Shiro 中,默认是支持权限通配符的,例如系统用户有如下一些权限: system:user:add system:user:delete system:user:select system:user:update … 现在给用户授权的时候,我们可以像上面这样,一个权限一个权限的配置,也可以直接用通配符: system:user:* 这个通配符就表示拥有针对用户的

  • 详解Spring中@Valid和@Validated注解用法

    目录 案例引入 @Valid 详解 @Validated 详解 @Valid 和 @Validated 比较 案例引入 下面我们以新增一个员工为功能切入点,以常规写法为背景,慢慢烘托出 @Valid 和 @Validated 注解用法详解. 那么,首先,我们会有一个员工对象 Employee,如下 : /** * 员工对象 * * @author sunnyzyq * @since 2019/12/13 */ public class Employee { /** 姓名 */ public St

随机推荐