使用不同的方式存入 Spring 容器中的 Bean 会有不同的命名规则。接下来让我们一起来一探究竟!!
@Component系列注解
@Component 系列注解顾名思义,就是 @Controller、@Service、@Repository、@Configuration 和 @Component 这些注解。
因为 Java 中的类提倡的是 Upper Camel Case,使用 @Component 系列注解存入 Spring 容器中的对象则默认是以 Lower Camel Case 的方式进行命名的。如下代码所示:
@Component
public class SpringBean {
}
将来 SpringBean 这个类的实例被放入 Spring 容器中会以 "springBean" 进行命名,当然也有特殊情况,比如下面这个类的实例就不满足上述命名规则:
@Component
public class UComponent {
}
这个类的实例将来在 Spring 容器中的命名是 "UComponent" 那么为什么会造成这样的结果呢?此时就需要查阅相关源代码了,在 Idea 当中搜索 BeanName。
追踪进去发现这个接口有三个实现类:
大部分情况我们都是使用注解来将对象交给 Spring 容器进行管理,所以大胆猜想此处就是 AnnotationBeanNameGenerator 这个实现类来进行 Bean 的命名的。顺藤摸瓜发现这个方法主要是获得了类的简类名并将其作为参数传递给 Introspector.decapitalize() 这个方法。如下代码段所示:
继续追踪这个方法,此时惊奇的发现,这个方法居然是 JavaSE 标准库的方法,也就是说 Spring 对于 Bean 的命名居然遵循的是 JavaSE 对 Bean 的命名规范。深入研究 JavaSE 标准库的这个方法:
根据该方法中这两处的核心逻辑我们可以得出结论:
- 当类名是以正常的大驼峰命名时,此方法返回类名的小驼峰形式(仅将首字母小写);
- 当类名首字母和第二个字母均是大写时,此方法直接返回原简类名。
随便观察一个 @Component 系列注解的源代码:
发现这个系列的注解都有一个 value 值,此时再次猜测这个值就是手动指定的 Bean 名称,经过测试发现确实如此,这里就不过多赘述了。
@Component 系列注解的 Bean 命名规则总结
- 没有指定注解的 value 值:
- 若类名是正常的大驼峰,则 Bean 将以类名的小驼峰形式命名。
- 若类名首字母和第二个字母均为大写,则 Bean 将以简类名直接命名。
- 指定注解的 value 值:直接以指定的 value 值命名。
@Bean注解
这个注解是加在方法上的,作用是将该注解标识的方法的返回值交给 Spring 容器进行管理。默认情况下,方法名就是 Bean 的名称。当然该注解可以传递参数来手动指定 Bean 名称,甚至可以指定多个名称,因为该注解的参数是一个数组。但是注意,手动命名时默认命名规则将失效。
@Bean({"u1", "us1"})
public User user() {
User user = new User();
user.setId(1);
user.setName("Java");
return user;
}
需要注意的是,如果多个 Bean 使用相同的名称,那么程序执行不会报错,而是第一个 Bean 之后的对象不会被存放到容器中,也就是说只有在第一次创建 Bean 的时候会将对象和 Bean 名称关联起来,后续再有相同名称的 Bean 对象存储时候,容器会自动忽略。如下列代码段所示:
@Component
public class Beans {
@Bean("stu")
public Student s1() {
return new Student(1, "张一");
}
@Bean("stu")
public Student s2() {
return new Student(1, "张二");
}
@Bean("stu")
public Student s3() {
return new Student(1, "张三");
}
}
class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
Student stu = context.getBean("stu", Student.class);
System.out.println(stu);
}
}
执行结果图:
这种多个 Bean 使用同一个名字的情况属于错误写法,尽量避免,以免出现预期不到的错误。