spring學習之源碼分析--SimpleAliasRegistry

SimpleAliasRegistry

實現了AliasRegistry接口,用ConcurrentHashMap存儲別名的對應關係,別名做爲key,name做爲value。segmentfault

類結構

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

返回是否容許別名覆蓋ide

protected boolean allowAliasOverriding() {
    // 默認容許覆蓋
    return true;
}

hasAlias

是否有別名,這裏要判斷循環依賴。this

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

移除別名spa

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

是否存在別名debug

public boolean isAlias(String name) {
    // 直接在aliasMap裏判斷
    return this.aliasMap.containsKey(name);
}

getAliases

根據bean名稱獲取別名code

public String[] getAliases(String name) {
    List<String> result = new ArrayList<>();
    synchronized (this.aliasMap) {
        // 主要的方法
        retrieveAliases(name, result);
    }
    // 把List轉數組
    return StringUtils.toStringArray(result);
}

retrieveAliases

獲取別名的實際方法,根據別名遞歸查找,直至找到全部的別名。blog

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;
}
相關文章
相關標籤/搜索