当前位置: 首页 > news >正文

站长之家 网站模板百度企业推广

站长之家 网站模板,百度企业推广,江苏seo站外推广靠谱,网站群 米拓前言 在 spring 容器中,允许通过名称或别名来获取 bean ,这个能力来自于顶层接口 AliasRegistry,分析类下属的关系图,可以看到,几乎所有主要容器都直接或间接的实现了 AliasRegistry 接口。 AliasRegistry 的结构非…

前言

在 spring 容器中,允许通过名称或别名来获取 bean ,这个能力来自于顶层接口 AliasRegistry,分析类下属的关系图,可以看到,几乎所有主要容器都直接或间接的实现了 AliasRegistry 接口。
在这里插入图片描述

AliasRegistry 的结构非常简单,主要的类就是 AliasRegistry 接口与他的实现类 SimpleAliasRegistry,后续的实现类基本都直接或间接的继承了 SimpleAliasRegistry

一、AliasRegistry

在 spring 的容器中,一个 bean 必须至少有一个名称,而一个名称可以有多个别名,别名亦可以有别名

通过 bean 的 id,或与该 id 直接、间接相关的别名,都可以从容器中获取到对应的 bean。

AliasRegistry 的作用就是定义这一套规则:

public interface AliasRegistry {void registerAlias(String name, String alias);void removeAlias(String alias);boolean isAlias(String name);String[] getAliases(String name);}

二、SimpleAliasRegistry

SimpleAliasRegistry 是直接基于 AliasRegistry 接口提供的简单实现类,他在内部维护了一个 Map 集合,以别名作为 key,别名对应的原名称作为 value:

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<String, String> aliasMap = new ConcurrentHashMap<>(16);// ...
}

SimpleAliasRegistry 中,我们在上文所提到的 id ,被称为标准名称 CanonicalName

1.注册别名

  1. 名称和别名相同则不注册
  2. 名称和已注册的名称相同,则不注册
  3. 如果别名不允许覆盖则抛出异常
  4. 存入映射关系
@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) {// 1.若别名与原名称一致,则直接移除该别名,否则继续后续处理if (alias.equals(name)) {this.aliasMap.remove(alias);if (logger.isDebugEnabled()) {logger.debug("Alias definition '" + alias + "' ignored since it points to same name");}}else {// 2.获取该别名的原名称String registeredName = this.aliasMap.get(alias);if (registeredName != null) {// 已对应的原名称和要对应的原名称相同,则放弃后续处理if (registeredName.equals(name)) {// An existing alias - no need to re-registerreturn;}// 若不允许重写原名称对应的别名,则直接抛出异常if (!allowAliasOverriding()) {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);// 建立别名与原名称的映射关系this.aliasMap.put(alias, name);if (logger.isTraceEnabled()) {logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");}}}
}

是否允许覆盖别名对应的原名称

registerAlias 方法中,调用了 allowAliasOverriding 方法,该方法在 SimpleAliasRegistry 中固定返回 true

protected boolean allowAliasOverriding() {return true;
}

该方法决定一个已经有对应原名称的别名,是否允许被重新被对应到另一个原名称。跟 HashMap 中的 afterNodeXXX 方法一样,这里很明显是留给子类重写的钩子方法。

检查是否存在循环引用

registerAlias 方法中,调用了 checkForAliasCircle 以检查别名是否存在 a -> b -> a 这样的循环引用:

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");}
}public boolean hasAlias(String name, String alias) {String registeredName = this.aliasMap.get(alias);// 判断该别名对应的原名称是否就是要找的原名称return ObjectUtils.nullSafeEquals(registeredName, name) ||// 递归检查别名的别名对应的原名称是否为要找的原名称(registeredName != null && hasAlias(name, registeredName));
}

因为在 SimpleAliasRegistry 中,一个名称作为另一个名称的别名后,该名称仍然允许有别的名称作为它的别名。

举个例子,实际场景中,可能会出现 a -> b -> c 这种情况,对应在 aliasMap 中则存在 b -> ac -> b 的引用关系。

此时,若想要确定 c 是否是 a 的别名,就需要在通过 c 取出 b 后,再向上递归根据 b 找到 a,把每一级的关系却判断一遍。

为什么要加锁

理解了循环引用的检查,也就不难理解加锁的必要性了。实际使用中,SimpleAliasRegistry 基本是作为单例使用,此时不可避免的可能会存在多线程调用 registerAlias 的可能性,即便 aliasMap 使用的 ConcurrentHashMap 本身是线程安全的,但是这不能阻止出现 a -> bb -> a 两个操作的同时发生,此时 ab 构成了循环引用,而每个线程中的 checkForAliasCircle 却未必能够正确的检测出问题。

2.获取名称

获取全部别名

@Override
public String[] getAliases(String name) {List<String> result = new ArrayList<>();synchronized (this.aliasMap) {retrieveAliases(name, result);}return StringUtils.toStringArray(result);
}private void retrieveAliases(String name, List<String> result) {// 遍历this.aliasMap.forEach((alias, registeredName) -> {// 名称和原名称相同if (registeredName.equals(name)) {result.add(alias);// 递归处理retrieveAliases(alias, result);}});
}

获取别名也很好理解,首先加锁同样的为了避免删除的同时注册别名导致的一些问题,然后递归调用的 retrieveAliases 也是为了防止出现“别名还有别名”的情况,getAliases 最终将返回该名称与该名称构成直接或间接引用关系的别名。

获取标准名称

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

该方法的作用是通过一个别名获得对应的标准名称。举个例子,假如现在存在如下别名引用关系:a -> b -> c -> d,则从 abcd 任意一个名称开始调用该方法,则最终都会返回 a

3.移除别名

@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");}}
}

4.名称转换

有时候,直接注册到 SimpleAliasRegistry 的名称和对应别名未必就是最想要,还需要替换占位符或者进行一些大小写转换的操作,这就需要通过 resolveAliases 方法来完:

public void resolveAliases(StringValueResolver valueResolver) {Assert.notNull(valueResolver, "StringValueResolver must not be null");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)) {this.aliasMap.remove(alias);}// 若别名与原名称不为空且不相同else if (!resolvedAlias.equals(alias)) {String existingName = this.aliasMap.get(resolvedAlias);// a.若转换后的别名已有对应的原名称,且与转换后的新原名称相同,则移除该别名的映射关系,否则报错if (existingName != null) {if (existingName.equals(resolvedName)) {// Pointing to existing alias - just remove placeholderthis.aliasMap.remove(alias);return;}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);}});}
}

其中,StringValueResolver 是一个函数式接口,它用于将一个字符串转为另一个字符串,也就是 resolve 的过程:

@FunctionalInterface
public interface StringValueResolver {@NullableString resolveStringValue(String strVal);
}

edName);
}
});
}
}


其中,`StringValueResolver` 是一个函数式接口,它用于将一个字符串转为另一个字符串,也就是 `resolve` 的过程:```java
@FunctionalInterface
public interface StringValueResolver {@NullableString resolveStringValue(String strVal);
}

resolveAliases 的过程基本与注册别名的方法 registerAlias 一致,本质上就是将原有的别名的与名称转换后再次建立映射关系,然后移除旧的映射关系。

http://www.lbrq.cn/news/2426239.html

相关文章:

  • 基于h5的个人网站建设推广关键词优化
  • 网络品牌网站建设行业关键词
  • 百度网站推广关键词怎么查合肥网站关键词优化公司
  • 怎么做类似美团的网站吗免费发帖推广网站
  • 做网站什么商品好百度官方
  • 邢台网站建设信息危机公关处理五大原则
  • 中文网站模板免费下载企业培训系统
  • 做建网站百度竞价推广计划
  • 廊坊百度推广电话长安seo排名优化培训
  • myeclipse做网站长春seo
  • 做网站用图片算侵犯著作权吗网站seo顾问
  • 张家港江阴网站设计免费建网站最新视频教程
  • 网站建设找工作宁波网络营销怎么做
  • 网站备案怎么弄中山谷歌推广
  • 郑州机械网站制作网络公司推广公司
  • 自定义wordpress后台企业网站设计优化公司
  • 企业站网络推广名风seo软件
  • 高唐网站建设服务商广州最新疫情情况
  • 自学java 做网站 多久小程序开发费用一览表
  • php 新闻网站开发最近热点新闻事件2023
  • 免费建网站哪个模板多百度关键词检测工具
  • 阿里云1m服务器可以搭建网站各种手艺培训班
  • 网投网站建设编程培训机构
  • 凡科建站怎么绑定自己的域名石家庄seo优化公司
  • 河南微网站开发长沙百度网站推广
  • 互联网公司排名2014老鬼seo
  • 企业建设网站注意事项全网网络营销推广
  • 网站开发保密协议范本下载整站seo服务
  • 网站百度排名网站多少钱
  • h5手机网站怎么做中国四大软件外包公司
  • Linux中ELF区域与文件偏移量的关系
  • Python并发编程:突破GIL枷锁,高效利用多核CPU
  • Linux的磁盘存储管理实操——(中)——逻辑卷管理实战
  • 基于大数据的旅游推荐系统 Python+Django+Hive+Vue.js
  • 数据结构 | 栈:构建高效数据处理的基石
  • Muduo库中单例模式详解