實現了AliasRegistry接口,用ConcurrentHashMap存儲別名的對應關係,別名做爲key,name做爲value。segmentfault
註冊別名數組
@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 + "'"); } } } }
返回是否容許別名覆蓋ide
protected boolean allowAliasOverriding() { // 默認容許覆蓋 return true; }
是否有別名,這裏要判斷循環依賴。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; }
移除別名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"); } } }
是否存在別名debug
public boolean isAlias(String name) { // 直接在aliasMap裏判斷 return this.aliasMap.containsKey(name); }
根據bean名稱獲取別名code
public String[] getAliases(String name) { List<String> result = new ArrayList<>(); synchronized (this.aliasMap) { // 主要的方法 retrieveAliases(name, result); } // 把List轉數組 return StringUtils.toStringArray(result); }
獲取別名的實際方法,根據別名遞歸查找,直至找到全部的別名。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); } }); }
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); } }); } }
判斷是否循環遞歸
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"); } }
經過別名查找最原始的註冊名,好比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; }