spring源码阅读之SimpleAliasRegistry

org.springframework.core.SimpleAliasRegistry.java 是一个关于spring注册别名的java类

重要变量:

/** Map from alias to canonical name */ private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

方法解读:

首先从注册方法入手:

@Override
public void registerAlias(String name, String alias)

注册考虑并发情况,增加同步锁

synchronized (this.aliasMap) 

alias和name必须不相同才会注册进aliasMap,否则不成功

if (alias.equals(name)) {
   this.aliasMap.remove(alias);

当name与当前alias的别名注册过的name不相同时,默认不允许覆盖,并抛出异常

if (!allowAliasOverriding()) {
   throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
         name + "': It is already registered for name '" + registeredName + "'.");
}

这里存在一个方法去防止注册循环,之后重点学习下

checkForAliasCircle(name, alias);

通过循环注册验证后,完成注册

this.aliasMap.put(alias, 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");
   }
}

如何处理循环别名引用

public boolean hasAlias(String name, String alias) {
   for (Map.Entry<String, String> entry : this.aliasMap.entrySet()) {
      String registeredName = entry.getValue();
      if (registeredName.equals(name)) {
         String registeredAlias = entry.getKey();
         return (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias));
      }
   }
   return false;
}

通过真实name确定是否存在alias,并判断registedAlias是否等于等待注册的alias,如果是,则返回true;如果相等,递归循环判断是否存在真名a的别名为b,b的别名为c,如果最初的参数为(a,c)这样环形引用的情况返回的是true.猜测:也就是说,在获取别名时,b和c都是a的alias,那么使用b和c作为别名,都可以获得相同的真名!验证:

public String canonicalName(String name) 
do {
   resolvedName = this.aliasMap.get(canonicalName);
   if (resolvedName != null) {
      canonicalName = resolvedName;
   }
}
while (resolvedName != null);

这里的循环判断正是处理这种循环引用的,以达到别名的别名也可以引用canonicalName.

获取alias,因为可能存在读写冲突,所以在筛选alias结果集的时候,需要同步

public String[] getAliases(String name)
synchronized (this.aliasMap) {
   retrieveAliases(name, result);
}
this.aliasMap.forEach((alias, registeredName) -> {
   if (registeredName.equals(name)) {
      result.add(alias);
      retrieveAliases(alias, result);
   }
});

这里也是处理循环引用的方式,通过canonicalName可以获取所有别名包括别名的别名.

之后还有一个方法:

public void resolveAliases(StringValueResolver valueResolver)

这个方法主要存储格式化处理后的name和alias

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/qq_40308199/article/details/80910879
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞