详解关于spring bean名称命名的那些事

 更新时间:2021年07月09日 10:59:39   作者:linyb极客之路  
每个bean都有一个或者多个标识符,这些标识符在容器中必须是唯一的,这篇文章主要给大家介绍了关于spring bean名称命名的那些事,需要的朋友可以参考下

前言

用了多年spring,一直想当然把spring默认的beanName当成是类名的首字母小写,比如HelloService其beanName为helloService。直到有天对接了供方厂商的接口,他有个类形如ABService,于是用

getBean(“aBService”)

的方式获取bean,结果取到是null,一开始以为是ABservice没注入,后面采用

getBean(ABService.class)

能成功获取到bean,说明ABService是有注入到IOC容器中,但是为啥用aBService获取不到bean?于是就用如下代码段,打印出相应ABService对应的beanName

applicationContext.getBeansOfType(ABService.class).forEach((beanName,bean)->{
            System.out.println(beanName + ":" + bean);
        });

打印出来的结果,如下

ABService:com.github.lybgeek.ABService@245b6b85

beanName竟然是ABService,这就和之前的想当然有出入。于是只好查看源码

02源码查看

源码查看有2种方式,本文的示例是springboot项目

01从main方法直接调试断点

从图可以看出如果是以扫描注解注入形式,其beanName的生成规则是由

org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName

决定。

ps: 这种直接从main启动类调试起,比较适用于时间比较多,或者排查毫无头绪

02带着问题查看,靠猜加验证的方式

利用idea的find Usage查找引用,比如ABService的注解@service,我们可以直接查看哪个引用到@Service,再猜测下beanName的生成规则

通过猜,我们基本上就可以定位出比较符合我们需求的方法

03源码验证

从上面的分析,我们可以知道如果是扫描bean注解注入的方式,其生成beanName规则,是在

org.springframework.context.annotation.AnnotationBeanNameGenerator

其生成规则代码如下

@Override
  public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    if (definition instanceof AnnotatedBeanDefinition) {
      String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
      if (StringUtils.hasText(beanName)) {
        // Explicit bean name found.
        return beanName;
      }
    }
    // Fallback: generate a unique default bean name.
    return buildDefaultBeanName(definition, registry);
  }

从代码段,我们可以看出,注解上有取名,比如@Service(“abService”),则beanName为abService,如果没有取名,则看

protected String buildDefaultBeanName(BeanDefinition definition) {
    String beanClassName = definition.getBeanClassName();
    Assert.state(beanClassName != null, "No bean class name set");
    String shortClassName = ClassUtils.getShortName(beanClassName);
    return Introspector.decapitalize(shortClassName);
  }

public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                        Character.isUpperCase(name.charAt(0))){
            return name;
        }
        char chars[] = name.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
    }

其实从代码我们就很容易看出答案了,如果类名前两个或以上个字母都是大写,则beanName和类名就一样了,不会进行首字母小写转换。

decapitalize这个方法的注释也写得很清楚,注释如下

/**
     * Utility method to take a string and convert it to normal Java variable
     * name capitalization. This normally means converting the first
     * character from upper case to lower case, but in the (unusual) special
     * case when there is more than one character and both the first and
     * second characters are upper case, we leave it alone.
     * <p>
     * Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays
     * as "URL".
     *
     * @param name The string to be decapitalized.
     * @return The decapitalized version of the string.
     */

04总结

通过扫描bean注解注入IOC时,如果不指定bean名称的默认规则是类名的首字母小写,如果类名前两个或以上个字母都是大写,那么bean名称与类名一样。

其实这个细节可能懂的都懂,本文的彩蛋主要是分享一下平时查看源码的一点心得吧,哈哈

到此这篇关于spring bean名称命名的文章就介绍到这了,更多相关spring bean名称命名内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java实现二叉树的创建及5种遍历方法(总结)

    java实现二叉树的创建及5种遍历方法(总结)

    下面小编就为大家带来一篇java实现二叉树的创建及5种遍历方法(总结)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • 关于web项目读取classpath下面文件的心得分享

    关于web项目读取classpath下面文件的心得分享

    这篇文章主要介绍了关于web项目读取classpath下面文件的心得,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • SpringBoot HikariCP连接池监控实现方案

    SpringBoot HikariCP连接池监控实现方案

    文章介绍了五种监控SpringBoot应用程序中HikariCP连接池状态和性能的工具和技术,包括SpringBootActuator、Micrometer、Prometheus+Grafana、HikariCP自带的Metrics以及NewRelic/Datadog等第三方服务,每种方法都有其特点和配置步骤
    2025-01-01
  • 详解Java的call by value和call by reference

    详解Java的call by value和call by reference

    在本篇文章里小编给大家总结了关于Java的call by value和call by reference的相关用法和知识点内容,需要的朋友们学习下。
    2019-03-03
  • SpringMVC中的表现层结果封装

    SpringMVC中的表现层结果封装

    这篇文章主要介绍了SpringMVC中的表现层结果封装,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • java8新特性之stream流中reduce()求和知识总结

    java8新特性之stream流中reduce()求和知识总结

    今天带大家回顾Java8的新特性,文中对stream流中reduce()求和的相关知识作了详细的介绍,对正在学习java的小伙伴们有很好地帮助,需要的朋友可以参考下
    2021-05-05
  • mybatis返回结果为Map问题

    mybatis返回结果为Map问题

    这篇文章主要介绍了mybatis返回结果为Map问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • springboot结合前端实现网页跳转功能实例

    springboot结合前端实现网页跳转功能实例

    今天处理Springboot统一异常拦截的时候,遇到了页面跳转的问题,这篇文章主要给大家介绍了关于springboot结合前端实现网页跳转功能的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • java后台处理前端传的json串方法

    java后台处理前端传的json串方法

    今天小编就为大家分享一篇java后台处理前端传的json串方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • Java 和 Kotlin Lambda 表达式示例详解

    Java 和 Kotlin Lambda 表达式示例详解

    Lambda 表达式是一种简洁的函数表达方式,可以把函数作为一个方法的参数,或者将代码块转换为数据传递,这篇文章主要介绍了Java 和 Kotlin Lambda 表达式示例详解,需要的朋友可以参考下
    2024-06-06

最新评论