Spring源码解析(五)-解析alias标签
2020-05-02 本文已影响0人
秋水畏寒
Spring版本
5.2.5.RELEASE
源码解读
首先看一下alias标签的使用方式:
<alias name="user" alias="use1"/>
name属性应用对应的bean,alias属性为该bean设置别名
查阅源码:
protected void processAliasRegistration(Element ele) {
String name = ele.getAttribute(NAME_ATTRIBUTE);
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
boolean valid = true;
if (!StringUtils.hasText(name)) {
getReaderContext().error("Name must not be empty", ele);
valid = false;
}
if (!StringUtils.hasText(alias)) {
getReaderContext().error("Alias must not be empty", ele);
valid = false;
}
if (valid) {
try {
// 注册别名
getReaderContext().getRegistry().registerAlias(name, alias);
}
catch (Exception ex) {
getReaderContext().error("Failed to register alias '" + alias +
"' for bean with name '" + name + "'", ele, ex);
}
// 通知监听器别名标签解析完毕
getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
}
}
该方法其实就做了俩步:
- 注册别名
- 通知监听器别名标签解析完毕
注册别名的逻辑如下:
@Override
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
synchronized (this.aliasMap) {
// 别名和实际名称一样,从aliasMap删除
// 之所以要删除,个人猜测是因为如果是空集合,删除是安全的,如果集合中存在,删除之后可以减少无谓的判断,提升性能
if (alias.equals(name)) {
this.aliasMap.remove(alias);
if (logger.isDebugEnabled()) {
logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
}
}
else {
// 获取alias对应的已经注册的name
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
// 如果俩者相同,所以已经注册过,直接返回
if (registeredName.equals(name)) {
// An existing alias - no need to re-register
return;
}
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
if (logger.isDebugEnabled()) {
logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
registeredName + "' with new target name '" + name + "'");
}
}
// 否则,检查是否存在循环指向
// 存在循环指向,则抛出异常
checkForAliasCircle(name, alias);
// 不存在循环指向,执行注册
this.aliasMap.put(alias, name);
if (logger.isTraceEnabled()) {
logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
}
}
}
}
其中,检查循环指向的代码如下:
protected void checkForAliasCircle(String name, String alias) {
if (hasAlias(alias, name)) {
throw new IllegalStateException("Cannot register alias '" + alias +
"' for name '" + name + "': Circular reference - '" +
name + "' is a direct or indirect alias for '" + alias + "' already");
}
}
可以看到交由hasAlias进行处理:
public boolean hasAlias(String name, String alias) {
String registeredName = this.aliasMap.get(alias);
// 如果已经注册的name(registeredName)和准备注册的name一致,那么直接返回true
// 否则,将registeredName作为别名,继续递归hasAlias进行判断
// 如果存在循环指向,那么必定会出现name和registeredName一致的情况
return ObjectUtils.nullSafeEquals(registeredName, name) || (registeredName != null
&& hasAlias(name, registeredName));
}
代码逻辑都比较清晰简单