杀死Spring - BeanFactory系列中的bean别名alias机制

杀死Spring - BeanFactory系列中的bean别名alias机制

Spring主要是通过SimpleAliasRegistry来完成别名功能的,它的类图继承关系如下:
在这里插入图片描述
那么它是怎么完成的呢?

一:域

	/*存储别名
	*若jdk >=1.5,返回java.util.concurrent.ConcurrentHashMap,否则
	*加载并返回edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap,否则
	*返回SynchronizedMap
	*存的内容是 别名 -> bean名,为什么这样存呢?因为一个bean可以有很多别名
	*/
    private final Map aliasMap = CollectionFactory.createConcurrentMapIfPossible(16);

二:方法

2.1:registerAlias
//注册别名
public void registerAlias(String name, String alias) {
        Assert.hasText(name, "'name' must not be empty");
        Assert.hasText(alias, "'alias' must not be empty");
        //若别名和bean名一样则删除
        if (alias.equals(name)) {
            this.aliasMap.remove(alias);
        } 
        //否则加入 别名 —> bean名
        else {
            if (!this.allowAliasOverriding()) {
                String registeredName = (String)this.aliasMap.get(alias);
                if (registeredName != null && !registeredName.equals(name)) {
                    throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'.");
                }
            }

            this.aliasMap.put(alias, name);
        }
}

protected boolean allowAliasOverriding() { return true; }
2.2:getAliases
//获取某个bean名的别名
public String[] getAliases(String name) {
        List aliases = new ArrayList();
        //获取aliasMap的锁
        synchronized(this.aliasMap) {
            Iterator it = this.aliasMap.entrySet().iterator();
			//遍历aliasMap,若bean名(value)跟name相等则将别名(key)加入aliases
            while(it.hasNext()) {
                Entry entry = (Entry)it.next();
                String registeredName = (String)entry.getValue();
                if (registeredName.equals(name)) {
                    aliases.add(entry.getKey());
                }
            }
			//返回aliases的数组形式
            return StringUtils.toStringArray(aliases);
        }
}
2.3:isAlias
//aliasMap中key值集合是否有name
public boolean isAlias(String name) { return this.aliasMap.containsKey(name); }
2.4:canonicalName
//简单名字canonical:最简单,经典的,规范的
//若aliasMap中存了 a->b,b->c,c->d返回的就是d
public String canonicalName(String name) {
        String canonicalName = name;
        String resolvedName = null;
		//我怎么感觉下面这个循环有毛病啊,要是aliasMap中存了 a->b,b->a那不死循环了
        do {
            resolvedName = (String)this.aliasMap.get(canonicalName);
            if (resolvedName != null) {
                canonicalName = resolvedName;
            }
        } while(resolvedName != null);

        return canonicalName;
    }
2.5:resolveAliases
//
public void resolveAliases(StringValueResolver valueResolver) {
        Assert.notNull(valueResolver, "StringValueResolver must not be null");
        //获取aliasMap的锁
        synchronized(this.aliasMap) {
            Map aliasCopy = new HashMap(this.aliasMap);
            Iterator it = aliasCopy.keySet().iterator();
			//复制一份aliasMap然后遍历它的key
            while(it.hasNext()) {
            	//别名
                String alias = (String)it.next();
                //当前别名对应的bean名
                String registeredName = (String)aliasCopy.get(alias);
                //替换别名中的占位符
                String resolvedAlias = valueResolver.resolveStringValue(alias);
                //替换bean名中的占位符
                String resolvedName = valueResolver.resolveStringValue(registeredName);
                //如果替换占位符后的别名和别名不相等
                if (!resolvedAlias.equals(alias)) {
                	//替换占位符后的别名对应的bean名和替换占位符后bean名不同就抛异常
                    String existingName = (String)this.aliasMap.get(resolvedAlias);
                    if (existingName != null && !existingName.equals(resolvedName)) {
                        throw new IllegalStateException("Cannot register resolved alias '" + resolvedAlias + "' (original: '" + alias + "') for name '" + resolvedName + "': It is already registered for name '" + registeredName + "'.");
                    }
					//存入替换占位符后别名 -> 替换占位符后的bean名
                    this.aliasMap.put(resolvedAlias, resolvedName);
		            //删除未替换占位符别名
		            this.aliasMap.remove(alias);
                } 
				//如果替换占位符后的bean名和没替换后的bean名不相等
				else if (!registeredName.equals(resolvedName)) {
					//存入未替换占位符的别名 -> 替换占位符的bean名
                    this.aliasMap.put(alias, resolvedName);
                }
            }

        }
}

三:总结

3.1在调用resolveAliases方法之前aliasMap中存的还是带有占位符的数据,而且占位符所对应的值在PlaceholderResolvingStringValuesResolver类的props中,这个变量的值是通过其构造方法赋予的,那么在获得其值我们还需要知道spring在启动时是怎么new PlaceholderResolvingStringValuesResolver的,也就是怎么将${}对应的值注入到props中的,这个请参考
3.2

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值