spring 5.1.4 debug 笔记 第一记 AliasRegistry

public interface AliasRegistry {

   /**
    * Given a name, register an alias for it.
    * @param name the canonical name
    * @param alias the alias to be registered
    * @throws IllegalStateException if the alias is already in use
    * and may not be overridden
    */
   void registerAlias(String name, String alias);    为你的xml中的声明的bean id 注册 别名

   /**
    * Remove the specified alias from this registry.
    * @param alias the alias to remove
    * @throws IllegalStateException if no such alias was found
    */
   void removeAlias(String alias);                   移除别名

   /**
    * Determine whether this given name is defines as an alias
    * (as opposed to the name of an actually registered component).
    * @param name the name to check
    * @return whether the given name is an alias
    */
   boolean isAlias(String name);                    判断是否存在此别名

   /**
    * Return the aliases for the given name, if defined.
    * @param name the name to check for aliases
    * @return the aliases, or an empty array if none
    */
   String[] getAliases(String name);                获取所有别名

}

 

我们来看一下它的一个实现类 

public class SimpleAliasRegistry implements AliasRegistry {

   /** Logger available to subclasses. */
   protected final Log logger = LogFactory.getLog(getClass());

   /** Map from alias to canonical name. */
   private final Map aliasMap = new ConcurrentHashMap<>(16);  定义一个存储 别名---->bean id      的map

//注册别名
   @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)) {    如果 别名 和 bean id 一样 移除 作为key的 别名 就算不存在也不会抛异常
            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);  从别名的map中获取 bean id
            if (registeredName != null) {  //如果真实存在
               if (registeredName.equals(name)) {  //但是已经注册过了 
                  // An existing alias - no need to re-register
                  return;                            结束程序
               }
               if (!allowAliasOverriding()) {  //是否允许别名复写 默认为true 否则抛异常 说 这个别名已经被注册了
                  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);// 检查bean id 和 别名 是否 别名陷入循环  往下看哦
            this.aliasMap.put(alias, name);  //添加 新的 别名 bean id 的映射关系
            if (logger.isTraceEnabled()) {
               logger.trace("Alias definition '" + alias + "' registered for name '" + 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.
    * @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 entry : this.aliasMap.entrySet()) {
         String registeredName = entry.getValue();    // 获取bean id 
         if (registeredName.equals(name)) {         如果此时bean id 和形参 name 相同 
            String registeredAlias = entry.getKey();   //获取 别名
            if (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias)) {
               return true;  //如果 别名 和 alias 相同的时候 说明 name 有别名 即 alias
                             //如果 别名 和 alias 第一次不相同的时候 把 别名 作为 bean id , alias作为 别名
                               重新传到 hasAlias 方法中
                               如果 registeredName.equals(name) 等于 true 说明 有别名 否则继续找
                               直到找不到 返回 false.
eg:
1、 name = "Y" alias = "Q"
2、 name = "X" alias = "N"
    
3、  name="C" alias = "B" 这种的直接找不到 返回false
第二种情况 X 的 别名有两个 一个是 U 另一个是N  我是对应两种情况说的 不明白的多看一下 很简单的,加油
            }
         }
      }
      return false;
   }

   @Override
   public void removeAlias(String alias) {
      synchronized (this.aliasMap) {
         String name = this.aliasMap.remove(alias);  //移除别名和bean id 的映射 如果不存在的话 抛出异常
         if (name == null) {
            throw new IllegalStateException("No alias '" + alias + "' registered");
         }
      }
   }

   @Override
   public boolean isAlias(String name) {
      return this.aliasMap.containsKey(name);  name 作为别名 是否存在 在aliasMap中
   }

   @Override
   public String[] getAliases(String name) {
      List result = new ArrayList<>();
      synchronized (this.aliasMap) {
         retrieveAliases(name, result);       //查询name 的别名 上面已经说了 一个bean id 可以有 多个别名 所以是数组 请看上面例子  retrieveAliases 解析 方法往下看
      }
      return StringUtils.toStringArray(result);
   }

   /**
    * 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 result) {
      this.aliasMap.forEach((alias, registeredName) -> {
         if (registeredName.equals(name)) {  //循环 aliasMap 如果bean id 包含 name 就往List 中 加入 别名
            result.add(alias);
            retrieveAliases(alias, result);  //因为一个bean id 可能有多个别名 而且别名可能 是另一个bean id 
所以在查 如果有 继续往List 中 加入 别名 直到 别名 作为bean id 这个条件不成立 然后 返回 List 
         }
      });
   }

   /**
    * Resolve all alias target names and aliases registered in this
    * factory, applying the given StringValueResolver to them.
    * 

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 aliasCopy = new HashMap<>(this.aliasMap); 新建一个跟aliasMap内容一样的Map 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); 如果 resolvedAlias是null 或者 resolvedName是null 或者二者相同 移除alias } else if (!resolvedAlias.equals(alias)) { 如果存在 ${} 符号 而且 resolvedAlias 才是最后的内容 String existingName = this.aliasMap.get(resolvedAlias); //获取 resolvedAlias 对应的 bean id if (existingName != null) { if (existingName.equals(resolvedName)) { //如果 bean id 相同 就是 一个bean id 对应两个key eg: 删除 那个 带有 ${}符号的 映射关系 最后只会剩下 这种情况 // Pointing to existing alias - just remove placeholder this.aliasMap.remove(alias); return; } // 如果不一样 抛出异常 这块着实不太理解 不知道怎么翻译 大概意思应该是 resolvedAlias 对应的bean id 即 existingName不等于 resolvedName的时候 抛出 不能注册 resolvedAlias 来源于 alias 作为 resolvedName的别名 它已经被 registeredName注册了 应该是 resolvedName 和 registeredName 不相同 不允许 同时带有${}的key value 键值对和 key value 共存 eg: ${xxx} -> ${yyyy} xxx->yyyy 只留下 xxx->yyyy 这种 键值对 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"); } } 因为涉及到循环 所以再说一遍 这就会造成循环 还有的就是 这种循环更深入 需要递归查询 /** * Determine the raw name, resolving aliases to canonical names. * @param name the user-specified name * @return the transformed name */ //这个方法 找到 一个不会充当 别名的bean id 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; } }

综上吧 这个代码虽然很短 但是想要理解逻辑需要自己写测试类 运行哦 一定从最小的部分下手 不然的话 你会吃大亏的 逻辑千千万 说实话 我很矛盾 真是又爱又恨 每次看spring源代码都是一知半解 不过今天写了一下 感觉不错哦 看是没用的 需要动手啊 加油 

估计没人转载我的文章吧 要是觉得还行呢 就附上链接吧

你可能感兴趣的:(spring源码,spring)