Spring 系列目錄(http://www.javashuo.com/article/p-kqecupyl-bm.html)html
public interface AliasRegistry { void registerAlias(String name, String alias); void removeAlias(String alias); boolean isAlias(String name); String[] getAliases(String name); }
AliasRegistry 接口十分簡單,提供了註冊、獲取及刪除指定 beanName 的別名的功能。下面咱們重點關注一下它的默認的實現 SimpleAliasRegistry。java
@Test public void test() { SimpleAliasRegistry aliasRegistry = new SimpleAliasRegistry(); aliasRegistry.registerAlias("beanA", "beanA_alias1"); aliasRegistry.registerAlias("beanA_alias1", "beanA_alias2"); // 1. 獲取別名對應的真實名稱 Assert.assertEquals("beanA", aliasRegistry.canonicalName("beanA_alias1")); Assert.assertEquals("beanA", aliasRegistry.canonicalName("beanA_alias2")); // 2. 獲取 beanA 的全部別名 Assert.assertEquals(2, aliasRegistry.getAliases("beanA").length); Assert.assertTrue(aliasRegistry.isAlias("beanA_alias1")); Assert.assertTrue(aliasRegistry.hasAlias("beanA", "beanA_alias2")); }
(1) 屬性spring
SimpleAliasRegistry 內部維護了一個隊列,存儲的是 <alais, name>api
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
(2) registerAliaside
註冊一個 alias源碼分析
@Override public void registerAlias(String name, String alias) { synchronized (this.aliasMap) { // 1. 別名和 bean 的名稱相同,不須要註冊,若是註冊了也要刪除 if (alias.equals(name)) { this.aliasMap.remove(alias); } else { String registeredName = this.aliasMap.get(alias); // 2. 別名已經註冊,若是註冊的名稱不相同是否容許覆蓋 if (registeredName != null) { if (registeredName.equals(name)) { return; } // 默認返回 true if (!allowAliasOverriding()) { throw new IllegalStateException(""); } } // 3. 註冊前檢查是否出現了循環註冊,如註冊 (a, b) 時已經註冊了 (b, a) checkForAliasCircle(name, alias); this.aliasMap.put(alias, name); } } }
(3) hasAliasthis
判斷指定的 name 是否有 alias 的別名。code
// a -> b -> c -> d -> e -> canonicalName,反向查找先找到最後一個 name // 而後一個一個判斷是否是要查找的 alias 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(); if (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias)) { return true; } } } return false; } // 檢查循環依賴 protected void checkForAliasCircle(String name, String alias) { if (hasAlias(alias, name)) { throw new IllegalStateException(""); } }
(4) getAliaseshtm
獲取指定 bean 的全部別名。blog
@Override public String[] getAliases(String name) { List<String> result = new ArrayList<>(); synchronized (this.aliasMap) { retrieveAliases(name, result); } return StringUtils.toStringArray(result); } private void retrieveAliases(String name, List<String> result) { this.aliasMap.forEach((alias, registeredName) -> { if (registeredName.equals(name)) { result.add(alias); retrieveAliases(alias, result); } }); }
(5) canonicalName
獲取一個 alias 的真實 name。
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; }
(5) resolveAliases
解析 alias 和 name 中的佔位符。
public void resolveAliases(StringValueResolver valueResolver) { synchronized (this.aliasMap) { // 由於遍歷時要修改 Map 集合,因此 copy 了一個新集合用於遍歷 Map<String, String> aliasCopy = new HashMap<>(this.aliasMap); aliasCopy.forEach((alias, registeredName) -> { String resolvedAlias = valueResolver.resolveStringValue(alias); String resolvedName = valueResolver.resolveStringValue(registeredName); // 1. 不存在或 resolvedAlias=resolvedName 時直接幹掉 if (resolvedAlias == null || resolvedName == null || resolvedAlias.equals(resolvedName)) { this.aliasMap.remove(alias); // 2. 別名解析後變化,兩種狀況:一是真實別名已經註冊;二是沒有註冊。 // 真實別名已經註冊又有兩種狀況:真實別名獲取的 name 和要註冊的 name 是否相等 } else if (!resolvedAlias.equals(alias)) { String existingName = this.aliasMap.get(resolvedAlias); // 2.1 別名已存在且相等只須要將含有佔位符的別名刪除便可,不然拋出異常 if (existingName != null) { if (existingName.equals(resolvedName)) { this.aliasMap.remove(alias); return; } throw new IllegalStateException(); } // 2.2 不存在,註冊前一樣須要檢查循環依賴 checkForAliasCircle(resolvedName, resolvedAlias); this.aliasMap.remove(alias); this.aliasMap.put(resolvedAlias, resolvedName); // 3. 真實名稱解析後變化直接替換 } else if (!registeredName.equals(resolvedName)) { this.aliasMap.put(alias, resolvedName); } }); } }
BeanDefinitionRegistry 管理全部註冊在 BeanFactory 上的 BeanDefinitio
public interface BeanDefinitionRegistry extends AliasRegistry { // 1. BeanDefinition 的註冊、刪除、獲取 void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException; void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; // 2. 其他的查詢操做 boolean containsBeanDefinition(String beanName); String[] getBeanDefinitionNames(); int getBeanDefinitionCount(); // 3. BeanFactory 是否註冊了這個 bean,最簡單的辦法是 isAlias(beanName) || containsBeanDefinition(beanName) boolean isBeanNameInUse(String beanName); }
BeanDefinitionRegistry 的默認實現爲 SimpleBeanDefinitionRegistry,它的實現也十分簡單,內部維護 Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64) 的隊列。
天天用心記錄一點點。內容也許不重要,但習慣很重要!