一、spring源码解析之RegisterAlias接口与实现类SimpleRegisterAlias

文章仅作记录所有,如有不当之处请指出。
一、RegisterAlias接口定义了对于alias的crud方法

public interface AliasRegistry {
		//新增与修改<alias,name>
    void registerAlias(String var1, String var2);
		//删除
    void removeAlias(String var1);
		//判断name是不是alias
    boolean isAlias(String var1);
		//获得指向name的alias链
    String[] getAliases(String var1);
}

二、SimpleRegisterAlias类
具体实现了RegisterAlias接口的各个功能,并且新增了重构容器和寻找原始name的方法。
1.实现registerAlias方法:

//新增<alias, name>
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)) {     //如果别名和真名一样则没有必要。        					
		this.aliasMap.remove(alias);           
    	if (this.logger.isDebugEnabled()) {    //记录日志            		
    			this.logger.debug("Alias definition '" + alias + "' ignored since it points to same name");           
    	}        
    } else {            //如果别名和真名不一样
    		String registeredName = (String)this.aliasMap.get(alias);  
            if (registeredName != null) {   //别名已对应的真名不为空
            	if (registeredName.equals(name)) { //别名已对应的真名和新增真名一样则不用新增
                   		return;                
                   }            
                if (!this.allowAliasOverriding()) { //是否允许覆盖, 不允许覆写报出异常
                    	throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'.");                
                }                
                if (this.logger.isDebugEnabled()) {    //记录日志                		
             			this.logger.debug("Overriding alias '" + alias + "' definition for registered name '" + registeredName + "' with new target name '" + name + "'");       
                }            
    		}            
    		this.checkForAliasCircle(name, alias); //判断别名与真名之间是否存在环
        	this.aliasMap.put(alias, name);        //新增
        	if (this.logger.isTraceEnabled()) {    //记录日志       
                this.logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");            
            }        
    }
    }
}
registerAlias方法中调用了checkForAliasCircle(name, alias)方法,其中的hasAlias方法是判断是否存在环的关键方法。
//判断是否有环,具体逻辑处理在hasAlias(name, alias)方法内
protected void checkForAliasCircle(String name, String alias) {    
    if (this.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");    
        }
 }
/**判断是否有环,不允许的情况有两种
*		1.<alias, name> <--> <name, alias>
		2.<alias, name> <--> <name, alias_> <--> <alias_, alias>
*/
public boolean hasAlias(String name, String alias) {    
    String registeredName = (String)this.aliasMap.get(alias);    
    return ObjectUtils.nullSafeEquals(registeredName, name) || 
        registeredName != null && this.hasAlias(name, registeredName);
  }   

//是否允许覆写
protected boolean allowAliasOverriding() {    
    return true;
}  
2.对removeAlias方法的实现
//移除别名对
public void removeAlias(String alias) {    
    synchronized(this.aliasMap) {        
        String name = (String)this.aliasMap.remove(alias);        
        if (name == null) {            //如果不存在这样的键值对则抛出异常
            throw new IllegalStateException("No alias '" + alias + "' registered");        			}
    }
}
3.对isAlias方法的实现
//判读名字是不是别名
public boolean isAlias(String name) {   
    return this.aliasMap.containsKey(name);
}
4.对getAliases方法的实现
//获得指向真名的别名链,如<a,b>,<b,name>
public String[] getAliases(String name) {    
    List<String> result = new ArrayList();    
    synchronized(this.aliasMap) {        
        this.retrieveAliases(name, result);    
    }   
    return StringUtils.toStringArray(result);
 }
//检索别名,找到满足getAliases方法的所有别名
private void retrieveAliases(String name, List<String> result) {    
    this.aliasMap.forEach((alias, registeredName) -> {      //遍历别名对  
        if (registeredName.equals(name)) {            //找到指向真名的别名
            result.add(alias);            
            this.retrieveAliases(alias, result);      //查找是否有指向这个别名的别名  
        }    
    });
}
5.新增的resolveAliases方法
//重构别名对容器
public void resolveAliases(StringValueResolver valueResolver) {    			
    Assert.notNull(valueResolver, "StringValueResolver must not be null");//断言valueResolver不为空    		
    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)) {  
                //变化后的别名不等于变化前别名
                if (!resolvedAlias.equals(alias)) {    
                    //变换后的别名已对应的真名
                    String existingName = (String)this.aliasMap.get(resolvedAlias); 
                    //该真名不为空时,总的来说变换后的别名不能一开始就有已对应的真名
                    if (existingName != null) {
                        //别名不一样,真名一样则移除
                        if (existingName.equals(resolvedName)) {   
                            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 + "'."); 
                    }  
                    //重构后也不能有环
                    this.checkForAliasCircle(resolvedName, resolvedAlias);
                    this.aliasMap.remove(alias);          
                    this.aliasMap.put(resolvedAlias, resolvedName);   
                    //别名没有变换,只有真名变了,直接put更新
                } else if (!registeredName.equals(resolvedName)) {  
                    this.aliasMap.put(alias, resolvedName);
                }
                //变换后,别名或者真名为空,或者别名等于真名直接移除
            } else {  
                this.aliasMap.remove(alias);  
            }
        });
    }
}
6.新增的canonicalName方法
//返回一个最原始的真名,只作为真名的真名
public String canonicalName(String name) {
    String canonicalName = name;
    String resolvedName;
    do {
        resolvedName = (String)this.aliasMap.get(canonicalName);
        if (resolvedName != null) { 
            canonicalName = resolvedName;
        }
    } while(resolvedName != null);
    return canonicalName;
}

三、对synchronized的一些理解
用于线程同步,解决线程安全问题(共享资源,多线程对共享资源的访问),以及保证正在进行的线程的操作可以被其他线程看见
三种使用方式:1.用于修饰实例方法
2.用于修饰静态方法
3.用于修饰代码块。
推荐一篇博客给大家了解synchronized
深入理解Java并发之synchronized实现原理

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值