Spring Bean 未指定名称的命名规则

2021-02-04

Spring IoC 容器中,指定名称的方式:

  • xml <bean> 配置 id 或 name
  • 注解指定 name
  • BeanDefinition 指定 name
  • register Bean 指定 beanName 参数

这些都比较好理解。

 

那如果未指定 Bean 的名称,Bean 会被如何命名呢?

常见的 Bean 命名规则如下:

  • xml <bean> 未指定 id、name, 生成规则:package.类名、package.类名#编号
  • @Component 未指定名称,生成规则:类名首字母小写 Test -> test;连续大写字母开头位置不变 TTest -> TTest
  • 静态内部类 + @Configuration|@Component 未指定名称,生成规则:外部类的名称首字母小写.静态内部类名称
  • @Bean 未指定名称,生成规则:方法名

小技巧:ListableBeanFactory 具有根据类型获取 bean 集合的能力,通过此方法可以查到所有注册的 Bean 名称

测试代码:

spring xml 配置

<bean class="constxiong.User">
	<property name="id" value="1"/>
	<property name="name" value="constxiong"/>
</bean>

<context:component-scan base-package="constxiong"/>


测试类

/**
 * 测试 Bean 的命名规则
 * @author ConstXiong
 */
public class Test {
	
	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/META-INF/spring-bean-name-generator.xml");
		// 指定名称:xml <bean> 指定 id、name;注解指定 name;BeanDefinition 指定 name;register Bean 指定名称
		// 比较容易理解不举例

		/**
		 * 常见的 Bean 命名规则
		 */
		// xml <bean> 未指定 id、name, 生成规则:package.类名、package.类名#编号
		User user1 = context.getBean("constxiong.User#0", User.class);
		System.out.println(user1);
		user1 = context.getBean("constxiong.User", User.class);
		System.out.println(user1);

		//@Component 未指定名称,生成规则:类名首字母小写 Test -> test;连续大写字母开头位置不变 TTest -> TTest
		Friend friend = context.getBean("friend", Friend.class);
		System.out.println(friend);

		//静态内部类 + @Configuration|@Component 未指定名称,生成规则:外部类的名称首字母小写.静态内部类名称
		Config config = context.getBean("test.Config", Config.class);
		System.out.println(config);

		//@Bean 未指定名称,生成规则:方法名
		User user2 = context.getBean("getUser", User.class);
		System.out.println(user2);

		// ListableBeanFactory 具有根据类型获取 bean 集合的能力,通过此方法可以查到所有注册的 Bean 名称
		System.out.println(context.getBeansOfType(User.class));
		System.out.println(context.getBeansOfType(Config.class));

		/**
		 * 详细的 Bean 命名规则,见 DefaultBeanNameGenerator、AnnotationBeanNameGenerator 两个类的 generateBeanName 方法
		 * DefaultBeanNameGenerator 涉及了 parent Bean - $child 的拼接;Factory Bean - $created 的拼接;相同类进行编号 - #0... 等操作
		 * AnnotationBeanNameGenerator 涉及了 获取注解指定的 name;去除包路径;类名首字母小写 的逻辑
		 * 往深了还有 bean name 覆盖问题
		 */

		// <context:component-scan base-package="constxiong"/> 可以添加 name-generator="constxiong.CustomBeanNameGenerator" 属性指定自定义 bean name 生成器
	}

	@Configuration
	static class Config {

	}
}

 

ConstXiong 备案号:苏ICP备16009629号-3