SimpleAliasRegistry
实现了AliasRegistry接口,用ConcurrentHashMap存储别名的对应关系,别名作为key,name作为value。
类结构
方法解析
registerAlias
注册别名
@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) {
//如果别名和name一样,则移除这个别名。
if (alias.equals(name)) {
this.aliasMap.remove(alias);
if (logger.isDebugEnabled()) {
logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
}
}
else {
//获取注册名
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 + "'");
}
}
}
}
allowAliasOverriding
返回是否允许别名覆盖
protected boolean allowAliasOverriding() {
// 默认允许覆盖
return true;
}
hasAlias
是否有别名,这里要判断循环依赖。
public boolean hasAlias(String name, String alias) {
for (Map.Entry entry : this.aliasMap.entrySet()) {
//获取注册名称
String registeredName = entry.getValue();
if (registeredName.equals(name)) {//如果注册名称跟当前name一样
String registeredAlias = entry.getKey();
//如果equals为true,说明循环依赖了
//如果为false,再调用hasAlias,比如a,b一组,b,c一组,此时c,a,多个循环依赖了
if (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias)) {
return true;
}
}
}
return false;
}
removeAlias
移除别名
public void removeAlias(String alias) {
synchronized (this.aliasMap) {
String name = this.aliasMap.remove(alias);
// 没有对应的别名,抛异常
if (name == null) {
throw new IllegalStateException("No alias '" + alias + "' registered");
}
}
}
isAlias
是否存在别名
public boolean isAlias(String name) {
// 直接在aliasMap里判断
return this.aliasMap.containsKey(name);
}
getAliases
根据bean名称获取别名
public String[] getAliases(String name) {
List result = new ArrayList<>();
synchronized (this.aliasMap) {
// 主要的方法
retrieveAliases(name, result);
}
// 把List转数组
return StringUtils.toStringArray(result);
}
retrieveAliases
获取别名的实际方法,根据别名递归查找,直至找到所有的别名。
private void retrieveAliases(String name, List result) {
this.aliasMap.forEach((alias, registeredName) -> {
if (registeredName.equals(name)) {
//如果注册名和当前name一样,用对应的别名,继续查找
//比如a,b一组,b,c一组,我们想获取a的别名,找到b后,会用b继续查找,找到c,此时,得到的值就是b、c
result.add(alias);
retrieveAliases(alias, result);
}
});
}
resolveAliases
public void resolveAliases(StringValueResolver valueResolver) {
Assert.notNull(valueResolver, "StringValueResolver must not be null");
synchronized (this.aliasMap) {
Map aliasCopy = new HashMap<>(this.aliasMap);
aliasCopy.forEach((alias, registeredName) -> {
// 获取解析后的别名
String resolvedAlias = valueResolver.resolveStringValue(alias);
// 获取解析后的注册名
String resolvedName = valueResolver.resolveStringValue(registeredName);
// 为空或者两个相等,移除掉
if (resolvedAlias == null || resolvedName == null || resolvedAlias.equals(resolvedName)) {
this.aliasMap.remove(alias);
} else if (!resolvedAlias.equals(alias)) { // 别名和解析后的别名不一样
// 获取注册名
String existingName = this.aliasMap.get(resolvedAlias);
// 如果存在
if (existingName != null) {
// 获取到的就是解析后的注册名,就把别名对应的移除。如果不一样,说明解析后的注册名被占用了,就抛异常
if (existingName.equals(resolvedName)) {
// Pointing to existing alias - just remove placeholder
this.aliasMap.remove(alias);
return;
}
throw new IllegalStateException(
"Cannot register resolved alias '" + resolvedAlias + "' (original: '" + alias +
"') for name '" + resolvedName + "': It is already registered for name '" +
registeredName + "'.");
}
//判断是否循环
checkForAliasCircle(resolvedName, resolvedAlias);
// 移除alias并设置解析后的映射
this.aliasMap.remove(alias);
this.aliasMap.put(resolvedAlias, resolvedName);
} else if (!registeredName.equals(resolvedName)) {
this.aliasMap.put(alias, resolvedName);
}
});
}
}
checkForAliasCircle
判断是否循环
protected void checkForAliasCircle(String name, String alias) {
// 调用hasAlias,循环调用抛异常
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");
}
}
canonicalName
通过别名查找最原始的注册名,比如a,b一组,b,c一组。
我们调用的参数是c,第一次循环,resolvedName为b,canonicalName为b,resolvedName不为空,会继续第二次循环,resolvedName为a,canonicalName为a,resolvedName不为空,第三次循环,resolvedName为空,canonicalName依然为a,跳出循环,返回a。
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;
}