Spring IOC学习(1)——SimpleAliasRegistry

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

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值