spring源码阅读之SimpleAliasRegistry

 2019-10-17 22:02  阅读(1264)
文章分类:Spring boot

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


来源:[]()

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> spring源码阅读之SimpleAliasRegistry

相关推荐