AliasRegistry学习

简介

在Spring框架中,AliasRegistry是一个接口,它定义了注册和管理bean别名的方法。别名允许你在Spring容器中为bean定义多个名称,这样你就可以使用这些别名来引用bean。

AliasRegistry接口的主要方法包括:

  • alias(String name, String alias): 为给定的bean名称注册一个别名。
  • aliasesFor(String name): 返回给定bean名称的所有别名。
  • unregisterAlias(String name, String alias): 注销给定bean名称的别名。

AliasRegistry接口通常与BeanDefinitionRegistry接口一起使用,后者允许你注册新的bean定义。Spring的DefaultListableBeanFactory类就实现了这两个接口,因此它既可以注册新的bean定义,也可以为这些bean定义注册别名。

源码

public interface AliasRegistry {

	/**
	 * 根据beanName 注册别名
	 */
	void registerAlias(String name, String alias);

	/**
	 * 移除别名
	 */
	void removeAlias(String alias);

	/**
	 判断是否是别名
	 */
	boolean isAlias(String name);

	/**
	 * 根据beanName获取别名集合
	 */
	String[] getAliases(String name);

}

实现类

public class SimpleAliasRegistry implements AliasRegistry {

	/** Logger available to subclasses. */
	protected final Log logger = LogFactory.getLog(getClass());

	/** key:别名 value:name */
	private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);


	@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 {
            String registeredName = this.aliasMap.get(alias);
            // 2.获取该别名的对应的原名称,若该别名已有对应的原名称,则:
            if (registeredName != null) {
                // a.已对应的原名称和要对应的原名称相同,则放弃后续处理
                if (registeredName.equals(name)) {
                    // An existing alias - no need to re-register
                    return;
                }

                // a.若不允许重写原名称对应的别名,则直接抛出异常
                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 + "'");
            }
        }
    }
}


	/**
	 * 是否允许覆盖别名对应的原名称
	 */
	protected boolean allowAliasOverriding() {
		return true;
	}
	public boolean hasAlias(String name, String alias) {
        //判断该别名对应的原名称是否就是要找的原名称
		String registeredName = this.aliasMap.get(alias);
        // 递归检查别名的别名对应的原名称是否为要找的原名称
		return ObjectUtils.nullSafeEquals(registeredName, name) || (registeredName != null
				&& hasAlias(name, registeredName));
	}

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

	@Override
	public boolean isAlias(String name) {
		return this.aliasMap.containsKey(name);
	}

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

	/**
	 * 名称转换
	 */
	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 placeholder
                        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 + "'.");
                }
                // 检查循环引用,然后移除旧别名与旧原名称的映射关系,建立新别名与新原名称的映射关系
                checkForAliasCircle(resolvedName, resolvedAlias);
                this.aliasMap.remove(alias);
                this.aliasMap.put(resolvedAlias, resolvedName);
            }
            else if (!registeredName.equals(resolvedName)) {
                this.aliasMap.put(alias, resolvedName);
            }
        });
    }
}


	/**
	 * 检查是否存在循环引用
	 */
	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 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;
	}

}

示例

import org.springframework.beans.factory.support.DefaultListableBeanFactory;  
import org.springframework.beans.factory.support.AliasRegistry;  
  
public class AliasRegistryExample {  
    public static void main(String[] args) {  
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();  
  
        // 注册一个新的bean定义  
        beanFactory.registerSingleton("myBean", new MyBeanClass());  
  
        // 为bean注册别名  
        ((AliasRegistry) beanFactory).alias("myBean", "alias1");  
        ((AliasRegistry) beanFactory).alias("myBean", "alias2");  
  
        // 获取并使用别名来引用bean  
        MyBeanClass bean = (MyBeanClass) beanFactory.getBean("alias1");  
        bean.doSomething();  
    }  
}  
  
class MyBeanClass {  
    public void doSomething() {  
        System.out.println("Doing something in MyBeanClass");  
    }  
}

在这个示例中,我们创建了一个DefaultListableBeanFactory实例,并使用它来注册一个新的bean定义。然后,我们通过将beanFactory强制转换为AliasRegistry来注册别名。最后,我们使用别名来从bean工厂中获取bean,并调用其方法。

需要注意的是,虽然AliasRegistry接口是公开的,但在大多数应用程序中,你不需要直接实现它。相反,你可以使用Spring容器(如ApplicationContext)来管理bean和它们的别名,这是更常见和推荐的做法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值