Spring源码阅读——Alias

Spring源码阅读——Alias

Alias:

管理别名的公共接口,定义了别名的增加删除等操作。

1. AliasRegistry接口

package org.springframework.core;

/**
 * Common interface for managing aliases. Serves as super-interface for
 * BeanDefinitionRegistry.
 * 为管理别名设计的公共接口,作为超级接口为BeanDefinitionRegistry服务
 */
public interface AliasRegistry {

    //为name注册别名alias
	void registerAlias(String name, String alias);

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

	//注册表里是否包含别名
	boolean isAlias(String name);

	//返回注册表中此name的所有别名
	String[] getAliases(String name);

}

2. BeanDefinitionRegistry

package org.springframework.beans.factory.support;

import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.AliasRegistry;

public interface BeanDefinitionRegistry extends AliasRegistry {

    //注册BeanDefinition
	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;

    //移除BeanDefnition
	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	//通过beanName获取BeanDefinition
	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	//是否包含BeanDefinition
	boolean containsBeanDefinition(String beanName);

	//获取注册表中所有BeanDefinition的名称
	String[] getBeanDefinitionNames();

	//获得注册表中BeanDefnition的数量
	int getBeanDefinitionCount();

	//给定的beanName是否被使用
	boolean isBeanNameInUse(String beanName);
}

3. SimpleAliasRegistry

package org.springframework.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.StringValueResolver;


public class SimpleAliasRegistry implements AliasRegistry {

	//存储注册信息
    //alias-beanName
	private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

	@Override
	public void registerAlias(String name, String alias) {
		//锁注册表
		synchronized (this.aliasMap) {
			//如果一样,移除alias
            if (alias.equals(name)) {
				this.aliasMap.remove(alias);
			}
			else {
                //获取当前别名在注册表中的规范名称
				String registeredName = this.aliasMap.get(alias);
				//已存在,不需要注册
                 if (registeredName != null) {
					if (registeredName.equals(name)) {
						// An existing alias - no need to re-register
						return;
					}
				}
                //效验规范名称是否指向当前别名
				checkForAliasCircle(name, alias);
                //别名和规范名的映射
				this.aliasMap.put(alias, name);
			}
		}
	}

	//是否允许重写注册表信息
	protected boolean allowAliasOverriding() {
		return true;
	}

	//alias和name的映射是否已经存在
	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;
	}

    //移除alias
	@Override
	public void removeAlias(String alias) {
		synchronized (this.aliasMap) {
			String name = this.aliasMap.remove(alias);
		}
	}

    //是否包含name
	@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);
					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;
	}
}

4. @AliasFor

表示别名,可以注解在自定义注解的两个属性上,来表示这两个属性具有相同的含义。


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};
    
    //......
}

可以看道@RequestMapping中的value和path用@AliasFor来注解的,说明path=value。

最大的作用就是:把多个元注解的属性组合在一起形成新的注解

5. 参考

https://www.jianshu.com/p/7b77b05407ae

https://www.cnblogs.com/sandyflower/p/10877291.html

String[] path() default {};

//......

}


可以看道@RequestMapping中的value和path用@AliasFor来注解的,说明path=value。

最大的作用就是:**把多个元注解的属性组合在一起形成新的注解**。

## 5. 参考

> https://www.jianshu.com/p/7b77b05407ae
>
> https://www.cnblogs.com/sandyflower/p/10877291.html

猜你喜欢

转载自blog.csdn.net/qq_40788718/article/details/106912243
今日推荐