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 {
}
}
详细的 Bean 命名规则,见 DefaultBeanNameGenerator、AnnotationBeanNameGenerator 两个类的 generateBeanName 方法
- DefaultBeanNameGenerator 涉及了 parent Bean - $child 的拼接;Factory Bean - $created 的拼接相同类进行编号 - #0... 等操作
- AnnotationBeanNameGenerator 涉及了 获取注解指定的 name;去除包路径;类名首字母小写 的逻辑
- 往深了还有 bean name 覆盖问题
完整代码:013-spring-bean-name-generator
【Java学习资源】整理推荐
- 自定义 Bean 作用域
- Bean 的作用域
- maven 集成 tomcat 以 jar 的方式打包 web 应用
- Spring 依赖注入与依赖查找来源的区别
- Spring 依赖注入的处理过程与 DependencyDescriptor 的说明
- Spring 各种 Aware 接口回调注入
- Spring Bean 生命周期内的 Exception 复现
- Spring 内建 Bean
- Spring Bean 的别名
- Spring Bean 未指定名称的命名规则
- Bean 何时被 GC
- Spring Bean 延迟加载
- ObjectFactory 与 BeanFactory 的区别
- Bean 销毁的方式与顺序
- Bean 初始化的方式与顺序
- Bean 的实例化方式
- Bean的注册方式
- 什么是 BeanDefinition?
- Spring IoC 容器启动时做了什么?
- BeanFactory 与 FactoryBean 的区别
- BeanFactory 与 ApplicationContext 的区别
- Spring IoC 依赖注入的实现方式
- Spring IoC 依赖注入(支持哪些数据类型?)
- Spring bean 依赖查找
- Spring-IoC
- Spring 的核心特性