Spring源码分析之AliasRegistry(2)

上一篇博客介绍了别名在spring中的简单使用,这篇来看一下AliasRegistry的具体实现。

别名管理器的具体实现

public interface AliasRegistry {

	/**
	 * 对一个name注册别名
	 */
	void registerAlias(String name, String alias);

	/**
	 * 移除一个别名
	 */
	void removeAlias(String alias);

	/**
	 * 检查一个name是否为别名
	 */
	boolean isAlias(String name);

	/**
	 * 获取一个name的所有别名
	 */
	String[] getAliases(String name);

}

这是spring中对AliasRegistry的定义,方法都是很明确的,接下来我们一个一个来解析。

AliasRegistry在spring中只有一个直接实现类SimpleAliasRegistry。先看一下SimpleAliasRegistry的简单使用,

public class Client {
  public static void main(String[] args) {
    AliasRegistry aliasRegistry = new SimpleAliasRegistry();
    aliasRegistry.registerAlias("userService", "userService1");
    aliasRegistry.registerAlias("userService", "userService2");
    System.out.println("userService的别名为 " + Arrays.toString(aliasRegistry.getAliases("userService")));
    System.out.println("userService1是否为别名:" + aliasRegistry.isAlias("userService1"));
    aliasRegistry.removeAlias("userService1");
    System.out.println("userService的别名为 " + Arrays.toString(aliasRegistry.getAliases("userService")));
    System.out.println("userService1是否为别名:" + aliasRegistry.isAlias("userService1"));
  }
}

对userService注册两个别名userService1,userService2,输出结果为

userService的别名为 [userService2, userService1]
userService1是否为别名:true
userService的别名为 [userService2]
userService1是否为别名:false

结果符合预期,接下来看一下源码实现。

public class SimpleAliasRegistry implements AliasRegistry {

	/** 
	 * 内部使用一个ConcurrentHashMap来存储,保证线程安全
	 */
	private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

	/**
	* 注册一个别名,存储方式为
	* 别名->本名 ,一个本名可以对应多个别名,如成龙有别名元楼、陈元龙,那么存储就是
	* 元楼->成龙
	* 陈元龙->成龙
	*/
	@Override
	public void registerAlias(String name, String alias) {
		synchronized (this.aliasMap) {
			//如果本名和别名一样就删除别名
			if (alias.equals(name)) {
				this.aliasMap.remove(alias);
			}
			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 + "'.");
					}
				}
				//检查是否有别名的循环如A->B B->C C->A就是一个循环
				checkForAliasCircle(name, alias);
				this.aliasMap.put(alias, name);
			}
		}
	}

	/**
	 * 是否允许将别名挂到别的本名上,默认允许
	 */
	protected boolean allowAliasOverriding() {
		return true;
	}

	/**
	 * 检查一个本名是否有指定别名,别名是可以递归注册的,如A->B B->C 那么C也是A的别名
	 */
	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;
	}

	/**
	* 删除一个别名
	*/	
	@Override
	public void removeAlias(String alias) {
		synchronized (this.aliasMap) {
			String name = this.aliasMap.remove(alias);
			if (name == null) {
				throw new IllegalStateException("No alias '" + alias + "' registered");
			}
		}
	}
	
	@Override
	public boolean isAlias(String name) {
		return this.aliasMap.containsKey(name);
	}

	@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);
			}
		});
	}

	/**
	 * 使用字符串解析器如占位符解析器解析所有别名
	 */
	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);
					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) {
		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 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;
	}

}

别名的存储方式为
别名->本名,允许递归注册别名,如A的别名为B,B的别名为C,那么C也是A的别名,如果C的别名是A,那么就会存在环的问题。

posted @ 2020-10-11 19:06  strongmore  阅读(175)  评论(0编辑  收藏  举报