文章仅作记录所有,如有不当之处请指出。
一、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实现原理