Spring中Bean别名的作用

在我们日常工作中,Bean的别名使用较少,因为大部分场景下,我们的Bean都是自己定义自己使用,比如:

@Component
public class UserServiceImpl1 implements UserService {
	public void test() {
		System.out.println("userServiceImpl1:test");
	}
}

@Component
public class OrderService {
	@Autowired()
	@Qualifier("userServiceImpl1")
	private UserService userService;

	public void test() {
		userService.test();
	}
}

在上述场景下,定义别名确实多此一举。但是如果在大型项目中,我们无法修改某些Bean的ID,在开发时又无法预先知道我们最终所注入的Bean的ID时,别名功能就很有用处了。下面是Spring文档中的例子:

假设在项目中有两个子模块A和B,两者分开开发。开发时子模块A和B定义它们的数据源DataSource的名字分别叫subsystemA-dataSource和subsystemB-dataSource。在项目组合运行时引入了C模块中的数据源myApp-dataSource,在不改动A、B模块代码的情况下,要让A、B模块都引用myApp-dataSource作为数据源,就需要为myApp-dataSource增加别名。使用XML的方式配置如下:

<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>

当然也有使用JavaConfig的配置方式:

@Configuration
public class AppConfig {
    @Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
    public DataSource dataSource() {
        // instantiate, configure and return DataSource bean...
    }
}

PS:在前文中同时提到了Bean的ID和Bean的名字的概念,我们明确一下:

  • Spring的所有单例Bean都有一个唯一的标识符,叫做Bean的ID;同时这个Bean又可以关联多个别名(alias),或者说名字(name)。
  • Spring所维护的单例池在概念上是这样一个集合:Map<ID,单例对象>
  • 别名池(aliasMap)的结构则是这样的:Map<alias, ID>

我们知道Spring从IOC容器中获取对象的方法叫做getBean(String name),Spring在获取对象时,由于不知道传入的参数到底是Bean的ID还是name,就会统一将其视为别名。Spring会先根据传入的name参数从aliasMap中获取Bean的ID,再从单例池中获取单例对象。下面是Spring获取Bean ID的源码:

类名:SimpleAliasRegistry
/**
 * Determine the raw name, resolving aliases to canonical names.
 * @param name the user-specified name
 * @return the transformed name
 */
public String canonicalName(String name) {
	String canonicalName = name;
	// Handle aliasing...
	String resolvedName;
	do {
		resolvedName = this.aliasMap.get(canonicalName);
		if (resolvedName != null) {
			canonicalName = resolvedName;
		}
	}
	while (resolvedName != null);
	return canonicalName;
}

注意源码里有个细节,就是获取ID的逻辑是在一个do-while循环中,这是因为有可能Bean定义的别名关联的是这个Bean的另一个别名,因此要一直循环,直到拿到真正的ID为止。所以下面的配置别名的方式Spring也是支持的,等于又为myApp-dataSource增加了一个别名subsystemC-dataSource:

<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>
<alias name="subsystemB-dataSource" alias="subsystemC-dataSource"/>
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值