SimpleAliasRegistry:提供bean对象的别名管理能力
/** Map from alias to canonical name
* 别名->规范名/另一个别名
*/
private final Map<String, String> aliasMap = new ConcurrentHashMap<String, String>(16);
/**
* 为name注册对应的别名alias
*/
@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) {
if (alias.equals(name)) {
//name和alias一样,则没有注册的必要;并且顺手移除掉
this.aliasMap.remove(alias);
}
else {
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
//alias已经注册过别名
if (registeredName.equals(name)) {
//重复注册,不用管了
// An existing alias - no need to re-register
return;
}
if (!allowAliasOverriding()) {
//不允许覆盖注册,则抛异常;SimpleAliasRegistry默认允许覆盖
throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
}
//检查循环别名的情况;如A->B,B->A
//疑问:假如存在两个bean,规范名为A、B;现调用registerAlias(A,B),这种情况如何检查?
checkForAliasCircle(name, alias);
//没有问题;最后成功注册
this.aliasMap.put(alias, name);
}
}
}
/**
* Return whether alias overriding is allowed.
* Default is {@code true}.
*/
protected boolean allowAliasOverriding() {
//默认允许覆盖注册
return true;
}
/**
* Determine whether the given name has the given alias registered.
* alias是否是name的别名
* @param name the name to check
* @param alias the alias to look for
* @since 4.2.1
*/
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)) {
//alias是name的直接别名或者间接别名
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");
}
}
}
/**
* name是否是一个别名
*/
@Override
public boolean isAlias(String name) {
return this.aliasMap.containsKey(name);
}
/**
* 获取name的所有别名
*/
@Override
public String[] getAliases(String name) {
List<String> result = new ArrayList<String>();
synchronized (this.aliasMap) {
retrieveAliases(name, result);
}
return StringUtils.toStringArray(result);
}
/**
* 递归获取name的所有直接、间接别名
* Transitively retrieve all aliases for the given name.
* @param name the target name to find aliases for
* @param result the resulting aliases list
*/
private void retrieveAliases(String name, List<String> result) {
for (Map.Entry<String, String> entry : this.aliasMap.entrySet()) {
String registeredName = entry.getValue();
if (registeredName.equals(name)) {
String alias = entry.getKey();
//name的直接别名
result.add(alias);
//name的间接别名
retrieveAliases(alias, result);
}
}
}
/**
* 用指定的某种解析器去解析aliasMap里的key和value;例如:解析key和value里的占位符;暂时不清楚用处
* Resolve all alias target names and aliases registered in this
* factory, applying the given StringValueResolver to them.
* <p>The value resolver may for example resolve placeholders
* in target bean names and even in alias names.
* @param valueResolver the StringValueResolver to apply
*/
public void resolveAliases(StringValueResolver valueResolver) {
Assert.notNull(valueResolver, "StringValueResolver must not be null");
synchronized (this.aliasMap) {
Map<String, String> aliasCopy = new HashMap<String, String>(this.aliasMap);
for (String alias : aliasCopy.keySet()) {
String registeredName = aliasCopy.get(alias);
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);
break;
}
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);
}
}
}
}
/**
* 检查循环别名
* Check whether the given name points back to the given alias as an alias
* in the other direction already, catching a circular reference upfront
* and throwing a corresponding IllegalStateException.
* @param name the candidate name
* @param alias the candidate alias
* @see #registerAlias
* @see #hasAlias
*/
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");
}
}
/**
* 根据name(可能为别名也可能为规范名)获取到最终对应的规范名;在doGetBean等场景发挥重要作用
* Determine the raw name, resolving aliases to canonical names.
* @param name the user-specified name
* @return the transformed 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;
}