Spring IOC(二)beanName 别名管理
Spring IOC(二)beanName 别名管理
Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)

一、AliasRegistry
public interface AliasRegistry {
void registerAlias(String name, String alias);
void removeAlias(String alias);
boolean isAlias(String name);
String[] getAliases(String name);
}
AliasRegistry 接口十分简单,提供了注册、获取及删除指定 beanName 的别名的功能。下面我们重点关注一下它的默认的实现 SimpleAliasRegistry。
1.2 API 使用
@Test
public void test() {
SimpleAliasRegistry aliasRegistry = new SimpleAliasRegistry();
aliasRegistry.registerAlias("beanA", "beanA_alias1");
aliasRegistry.registerAlias("beanA_alias1", "beanA_alias2");
// 1. 获取别名对应的真实名称
Assert.assertEquals("beanA", aliasRegistry.canonicalName("beanA_alias1"));
Assert.assertEquals("beanA", aliasRegistry.canonicalName("beanA_alias2"));
// 2. 获取 beanA 的所有别名
Assert.assertEquals(2, aliasRegistry.getAliases("beanA").length);
Assert.assertTrue(aliasRegistry.isAlias("beanA_alias1"));
Assert.assertTrue(aliasRegistry.hasAlias("beanA", "beanA_alias2"));
}
1.2 SimpleAliasRegistry 源码分析
(1) 属性
SimpleAliasRegistry 内部维护了一个队列,存储的是 <alais, name>
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
(2) registerAlias
注册一个 alias
@Override
public void registerAlias(String name, String alias) {
synchronized (this.aliasMap) {
// 1. 别名和 bean 的名称相同,不需要注册,如果注册了也要删除
if (alias.equals(name)) {
this.aliasMap.remove(alias);
} else {
String registeredName = this.aliasMap.get(alias);
// 2. 别名已经注册,如果注册的名称不相同是否允许覆盖
if (registeredName != null) {
if (registeredName.equals(name)) {
return;
}
// 默认返回 true
if (!allowAliasOverriding()) {
throw new IllegalStateException("");
}
}
// 3. 注册前检查是否出现了循环注册,如注册 (a, b) 时已经注册了 (b, a)
checkForAliasCircle(name, alias);
this.aliasMap.put(alias, name);
}
}
}
(3) hasAlias
判断指定的 name 是否有 alias 的别名。
// a -> b -> c -> d -> e -> canonicalName,反向查找先找到最后一个 name
// 然后一个一个判断是不是要查找的 alias
public boolean hasAlias(String name, String alias) {
for (Map.Entry<String, String> entry : this.aliasMap.entrySet()) {
String registeredName = entry.getValue();
if (registeredName.equals(name)) {
String registeredAlias = entry.getKey();
if (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias)) {
return true;
}
}
}
return false;
}
// 检查循环依赖
protected void checkForAliasCircle(String name, String alias) {
if (hasAlias(alias, name)) {
throw new IllegalStateException("");
}
}
(4) getAliases
获取指定 bean 的所有别名。
@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);
}
});
}
(5) canonicalName
获取一个 alias 的真实 name。
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;
}
(5) resolveAliases
解析 alias 和 name 中的占位符。
public void resolveAliases(StringValueResolver valueResolver) {
synchronized (this.aliasMap) {
// 因为遍历时要修改 Map 集合,所以 copy 了一个新集合用于遍历
Map<String, String> aliasCopy = new HashMap<>(this.aliasMap);
aliasCopy.forEach((alias, registeredName) -> {
String resolvedAlias = valueResolver.resolveStringValue(alias);
String resolvedName = valueResolver.resolveStringValue(registeredName);
// 1. 不存在或 resolvedAlias=resolvedName 时直接干掉
if (resolvedAlias == null || resolvedName == null || resolvedAlias.equals(resolvedName)) {
this.aliasMap.remove(alias);
// 2. 别名解析后变化,两种情况:一是真实别名已经注册;二是没有注册。
// 真实别名已经注册又有两种情况:真实别名获取的 name 和要注册的 name 是否相等
} else if (!resolvedAlias.equals(alias)) {
String existingName = this.aliasMap.get(resolvedAlias);
// 2.1 别名已存在且相等只需要将含有占位符的别名删除即可,否则抛出异常
if (existingName != null) {
if (existingName.equals(resolvedName)) {
this.aliasMap.remove(alias);
return;
}
throw new IllegalStateException();
}
// 2.2 不存在,注册前同样需要检查循环依赖
checkForAliasCircle(resolvedName, resolvedAlias);
this.aliasMap.remove(alias);
this.aliasMap.put(resolvedAlias, resolvedName);
// 3. 真实名称解析后变化直接替换
} else if (!registeredName.equals(resolvedName)) {
this.aliasMap.put(alias, resolvedName);
}
});
}
}
二、BeanDefinitionRegistry
BeanDefinitionRegistry 管理所有注册在 BeanFactory 上的 BeanDefinitio
public interface BeanDefinitionRegistry extends AliasRegistry {
// 1. BeanDefinition 的注册、删除、获取
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 2. 其余的查询操作
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
// 3. BeanFactory 是否注册了这个 bean,最简单的办法是 isAlias(beanName) || containsBeanDefinition(beanName)
boolean isBeanNameInUse(String beanName);
}
BeanDefinitionRegistry 的默认实现为 SimpleBeanDefinitionRegistry,它的实现也十分简单,内部维护 Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64) 的队列。
每天用心记录一点点。内容也许不重要,但习惯很重要!
Spring IOC(二)beanName 别名管理的更多相关文章
- Spring:源码解读Spring IOC原理
Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...
- Spring IOC原理解读 面试必读
Spring源码解析:Bean实例的创建与初始化 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. IoC容器 ...
- Spring源码解读Spring IOC原理
一.什么是Ioc/DI? IoC 容器:最主要是完成了完成对象的创建和依赖的管理注入等等. 先从我们自己设计这样一个视角来考虑: 所谓控制反转,就是把原先我们代码里面需要实现的对象创建.依赖的代码,反 ...
- Spring IOC设计原理解析:本文乃学习整理参考而来
Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...
- Spring IOC的配置使用(转)
转:http://www.cnblogs.com/linjiqin/p/3408306.html Spring IOC的配置使用 1.1.1 XML配置的结构一般配置文件结构如下: <beans ...
- Spring IOC的配置使用
1.1.1 XML配置的结构一般配置文件结构如下: <beans> <import resource=”resource1.xml” /> <bean id=”bean1 ...
- Spring IOC之Bean 概述
1.Bean概述 一个Spring IOC容器管理一个或者多个bean.这些bean是根据你提供给容器的配置数据信息创建的,例如XML形式的的定义. 在容器内部,这些bean的定义表示为BeanDef ...
- Spring IOC 总结
IOC 简介 IOC是(Inversion of Control,控制反转)的简写.Spring提供IOC容器,将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的的过度程序耦合.它由DI( ...
- 【Spring】Spring IOC
Spring IOC IOC 的常用注解 小节源码 之前的 XML 配置: <bean id="accountService" class="cn.parzulpa ...
随机推荐
- mongodb突然出现一些特别奇葩的事
mongo突然出现一些奇葩的事,如数据都还在,但某个命令敲下去了.啥东西都没有返回给我们. 往往这个时候特别的郁闷,找不出问题所在. 不用太担心,看看版本,多半是mongo的版本太老了,有些命令已经过 ...
- 12.13java过关测试
库存物资管理系统: 1.首先建两个数据表,一个pass用于商品的增删改查,一个passd记录商品的出库与入库信息: 2.建两个实体类,用来传递商品与单据的信息 3.在添加与删除时,填写入库或者出库单据 ...
- 1、CDH 搭建Hadoop在安装之前(存储空间规划)
Cloudera Manager的存储空间规划 最低要求角色: 完全管理员 Cloudera Manager跟踪许多后台进程中的服务,作业和应用程序的度量标准.所有这些指标都需要存储.根据组织的大小, ...
- SQL Select语句完整的执行顺序(转)
SQL Select语句完整的执行顺序: 1.from子句组装来自不同数据源的数据: 2.where子句基于指定的条件对记录行进行筛选: 3.group by子句将数据划分为多个分组: 4.使用聚集函 ...
- ChromDevTools
[ChromDevTools] 1.如何打开DevTools. 在Chrome菜单中选择 更多工具 > 开发者工具 在页面元素上右键点击,选择 “检查” 使用 快捷键 F12 2.切换 Devi ...
- Unity3D中的Quality
Quality Level:质量等级,默认为打包最低的那个等级 Name:质量级别的名称 Pixel Light Count:像素灯数量(前向渲染使用的像素灯的最大数量) Texture Qualit ...
- JMeter学习(三十四)使用jmeter来发送json/gzip格式数据(转载)
转载自 http://www.cnblogs.com/yangxia-test 一.使用jmeter来发送gzip数据 有时候我们需要模拟在客户端将数据压缩后, 发送(post)到服务器端. 通常这种 ...
- 牛客练习赛43-F(简单容斥)
题目链接:https://ac.nowcoder.com/acm/contest/548/F 题意:简化题意之后就是求[1,n]中不能被[2,m]中的数整除的数的个数. 思路:简单容斥题,求[1,n] ...
- c++三种进制格式
来源:c++ primer plus 常用的进制有二进制,八进制,十进制,十六进制,在c++的头文件iostream里除了提供了endl控制符之外,还提供了控制进制的控制符,(不含二进制),分别是八进 ...
- JMeter监控内存及CPU ——plugin插件监控被测系统资源方法
jmeter中也可以监控服务器的CPU和内存使用情况,但是需要安装一些插件还需要在被监测服务器上开启服务. 1.需要的插件准备 JMeterPlugins-Standard-1.3.1.zip 下载 ...