1

SimpleAliasRegistry

实现了AliasRegistry接口,用ConcurrentHashMap存储别名的对应关系,别名作为key,name作为value。

类结构

image.png

方法解析

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<String, String> 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<String> result = new ArrayList<>();
    synchronized (this.aliasMap) {
        // 主要的方法
        retrieveAliases(name, result);
    }
    // 把List转数组
    return StringUtils.toStringArray(result);
}

retrieveAliases

获取别名的实际方法,根据别名递归查找,直至找到所有的别名。

private void retrieveAliases(String name, List<String> 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<String, String> 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;
}

大军
847 声望183 粉丝

学而不思则罔,思而不学则殆