【Spring】透过Spring源码查看Bean的命名转换规则

简介: 【Spring】透过Spring源码查看Bean的命名转换规则

测试观察

  • 首先,如果要将指定的对象存放到Spring中,在Spring的配置文件中的扫描包路径一定不能错,这样我们在这个包中所包含的类前加上【五大类注解】,就可以将对象存储到Spring中的
<content:component-scan base-package="com.spring.demo"></content:component-scan>

image.png

  • 然后我便在这个包下写了个UserController 类,并且加上了【@Controller】注解,此时Spring在加载的时候就会存储改对象
@Controller
public class UserController {
    public void SayHello(){
        System.out.println("do SayHello()");
    }
}
  • 此时看到,我在App类中去获取到了这个Bean对象,而且使用的是【名称 + 类名】的形式,==这种形式就可以防止Spring中存储多个Bean对象而造成的冲突问题==
  • 但是呢,我就卡在了这里,不知道该去写什么名称?因为根本没有在Spring中写明Id值

image.png

  • 首先我想到的是这个名称会不会就是类名呢?但是在我进行尝试之后却发现并不是这样,编译器报出了异常说No bean named 'UserController' available

image.png

  • 然后我又想到了Java的命名规范是【小驼峰】,一般去通过这个类实例化对象的时候都是将首字母进行一个小写,其余不变,于是当我使用这个名称进行传递的时候,程序运行就没有问题了

image.png

那我首先猜测它的命名就是这样规定的,但是有没有特例呢?

  • 此时我又去定义了一个类,将其类名取成了两个大写字母开头的,看看这样子的命名是否还会以【小驼峰】的形式去进行转换
@Controller
public class SController {
    public void SayHello(){
        System.out.println("do SayHello()");
    }
}
  • 但是当我在看运行结果的时候,却发现这样小驼峰的形式似乎行不通了

image.png

  • 但是当我在将名称改回【类名】的时候,却发现又可以运行了,这是为什么呢?里面的转换规则又是怎样的?这需要我再去研究一番:mag:

image.png

原理探究

通过上面的测试可以看出,Spring对于这个Bean对象的命名转换是存在一定规则的,因为【在Spring中,约定大于俗成】

  • 接下去我就通过查看Spring源码的方式带读者来探究一下到底这个Spring内部对于这个Bean的命名转换规则是怎样的,虽然Spring框架的代码都是开源的,但是要精准地找到对应想要的代码逻辑可不简单,需要层层深入地进行探访
  1. 首先第一步,我们可以按两下【shift】键,便会跳出IDEA的搜索框,在这个里面你可以去搜寻当前项目中所有的类、接口,以查看它们的内部实现。然后我便发现了一个类叫做AnnotationBeanNameGenerator,翻译一下即为【注释Bean名称生成器】,那我猜测命名规范的代码逻辑可能就在这个类中

image.png

  1. 当我们进入到这个类后,就可以去寻找其对应的方法了,那个方法是和BeanName有关联的,首先点击右侧的【结构】我们便可以看到这个类中到底有哪些方法,那一看我们就可以观察到有generateBeanName()这个方法,点到对应的方法后再进行观察,便发现其最后返回时又去调用了一个方法,于是我继续按住Ctrl键点进去

image.png

  • 点进去发现里面又是一个方法,一些复杂的逻辑其实就是以这样一种嵌套的形式进行的,各个类、接口之间的方法调来调去

image.png

  • 然后看到这是下面的这个方法buildDefaultBeanName()生成默认Bean名称

image.png

  • 最后的话我们看到它在return的时候似乎又通过一个类名去调用了一个方法,然后传入了这个ClassName,那我继续点进去后就发现我似乎已经不处于Spring框架的源码中了,而是来到了JDK中
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);
}
  • 我们可以点击右上角的这个按钮【选择打开的文件】去找到这个类所对应的位置

image.png

  • 最后我这边顺腾摸瓜地去查找就看到这个类是java.deskop包下的一个类,那么我们在查看Spring源码的时候最终还是来到了JDK下,这个可以说明一点:Bean的命名并不是乱取的,而是使用JDK的一个命名标准去进行命名的

image.png

然后我们就可以去看看JDK中对于命名的规范到底是怎样的:computer:

  • 可以看到很明显的这里是有两种情况,若是首字母和第二个字母都是大写的话,那就返回原来的名称;第二种情况则是将字符串首先转换成了字符数组,然后再将第一位变成小写
  • 那看到这里的话其实我已经是明白了,原来Spring对于Bean的这个命名规则是这样的

image.png

总结一下

最后的话我们来总结一下本次查看源码的收获吧🍚

通过查看Spring的源码我们进入到了JDK中,经过代码的阅读将Bean的命名转换总结了以下两点

  1. 默认情况:使用原类名首字母小写就能读取到Bean对象
  2. 特例:如果首字母和第二字母都是大写的情况下,那么Bean名称就是原类名

在学习Spring框架的过程中,初学者难免会遇到不理解的地方,因为Spring是一个IoC容器,会通过DI依赖注入的形式帮我们自动地去管理对象,所以内部的细节便不得而知,但我们可以通过【阅读源码】的方式来进行理解,去看看大佬是怎么思考的🤔

相关文章
|
15天前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
99 26
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
2月前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
2月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
2月前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
74 6
|
2月前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
159 3
|
2月前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
74 2
|
2月前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
50 1
|
27天前
|
XML Java 应用服务中间件
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
208 17
Spring Boot 两种部署到服务器的方式
|
27天前
|
Dart 前端开发 JavaScript
springboot自动配置原理
Spring Boot 自动配置原理:通过 `@EnableAutoConfiguration` 开启自动配置,扫描 `META-INF/spring.factories` 下的配置类,省去手动编写配置文件。使用 `@ConditionalXXX` 注解判断配置类是否生效,导入对应的 starter 后自动配置生效。通过 `@EnableConfigurationProperties` 加载配置属性,默认值与配置文件中的值结合使用。总结来说,Spring Boot 通过这些机制简化了开发配置流程,提升了开发效率。
61 17
springboot自动配置原理