Spring源码分析:AbstractBeanFactory抽象实现分析

1、AbstractBeanFactory概览

AbstractBeanFactory继承自FactoryBeanRegistrySupport,并且实现了ConfigurableBeanFactory接口,是BeanFactory的核心实现类。
BeanFactory实现的抽象基类,提供了ConfigurableBeanFactory SPI的全部功能。AbstractBeanFactory并没有实现ListableBeanFactory接口:因此也可以用作从后台资源获取bean定义的bean工厂实现的基类(在后台资源中,访问bean定义是一个昂贵的操作)。

这个类提供了一个单例缓存(通过它的基类DefaultSingletonBeanRegistry、单例/原型确定、FactoryBean处理、别名、子bean定义的bean定义合并以及bean销毁(DisposableBean接口、自定义销毁方法)。此外,通过实现HierarchicalBeanFactory接口,它可以管理bean工厂层次结构(在出现未知bean的情况下委托给父节点)。

子类要实现的主要模板方法是getBeanDefinition和createBean,分别为给定bean名称检索bean定义和为给定bean定义创建bean实例。这些操作的默认实现可以在DefaultListableBeanFactory和AbstractAutowireCapableBeanFactory中找到。
在这里插入图片描述从类层级结构我们可以看到除了我们在Spring源码分析:BeanFactory体系详解一(接口分析)中分析相关接口以外,AbstractBeanFactory还实现了AliasRegistry、SingletonBeanRegistry接口。

1.1 AliasRegistry接口分析

AliasRegistry(别名注册表): 管理别名的通用接口。作为BeanDefinitionRegistry的超级接口。

public interface AliasRegistry {
   

	// 为给定名称注册一个别名。如果别名已经在使用且不能被重写,将抛出异常IllegalStateException
	void registerAlias(String name, String alias);

	// 移除指定的别名。如果别名不存在将抛出异常IllegalStateException
	void removeAlias(String alias);

	// 确定给定的名称是否定义为别名(而不是实际注册的组件的名称)。
	boolean isAlias(String name);

	// 如果已定义,则返回给定名称的别名。如果未定义,返回空数组
	String[] getAliases(String name);

}

1.2 SingletonBeanRegistry接口分析

SingletonBeanRegistry(单例bean注册表):该接口为单例bean实例定义注册表。可以由BeanFactory实现实现,以便以统一的方式公开它们的单例管理工具。ConfigurableBeanFactory接口扩展了这个接口。

public interface SingletonBeanRegistry {
   

	// 将给定的单例对象和bean注册到注册表。给定的单例应该完全初始化,不支持初始化回调和销毁回调。
	// 如果在一个完整的BeanFactory运行过程,需要bean支持初始化回调、销毁回调,需要注册一个BeanDefinition。
	// 该方法通常在注册表配置期间调用,但是也可以用于单例的运行是注册。因此该注册表的实现应该同步单例的访问;
	// 如果BeanFactory支持单例的延迟初始化,那么无论如何都必须同步单例的访问。
	void registerSingleton(String beanName, Object singletonObject);

	// 返回在给定名称下注册的(原始的)单例对象。只检查已经实例化的单例;不返回尚未实例化的单例bean定义的对象。
	// 这个方法的主要目的是访问手工注册的单例(参见registerSingleton)。
	// 该方法也可以用于以原始方式访问由BeanDefinition定义,并且已经创建的单例。
	// 注意: 这个查找方法不知道FactoryBean前缀或别名。在获得单例实例之前,您需要首先解析规范bean名称。
	@Nullable
	Object getSingleton(String beanName);

	// 检查此注册表是否包含给定名称的单例实例。只检查已经实例化的单例;对于尚未实例化的Bean定义单例不返回true。
	// 这个方法的主要目的是检查手工注册的单例。还可以用于检查bean定义定义的单例是否已经创建。
	// 要检查bean工厂是否包含具有给定名称的bean定义,请使用ListableBeanFactory的containsBeanDefinition
	// 同时调用containsBeanDefinition和containsSingleton将确定bean工厂是否包含给定名称的本地bean实例。
	// 工厂的containsBean方法检查是否包含给定名称的bean(无论手动注册的还是由bean定义创建的),还检查祖先工厂。
	// 注意:这个查找方法不知道FactoryBean前缀或别名。在检查单例状态之前,您需要首先解析规范bean名称。
	boolean containsSingleton(String beanName);

	// 返回在此注册表中注册的单例bean的名称。只检查已经实例化的单例;不返回尚未实例化的单例bean定义的名称。
	// 这个方法的主要检查手工注册的单例。还可以用来检查使用BeanDefiniton定义的,且已经创建的单例。
	String[] getSingletonNames();

	// 返回Bean工厂的单例数。仅仅统计已经创建创建的实例。不包含有BeanDefinition定义,但未创建的单例。
	// 该方法主要用于返回手动注册的单例。也用于返回BeanDefinition定义的,且已完成创建的单例。
	int getSingletonCount();

	// 返回此注册表使用的单例互斥锁(对于外部协作者)。
	Object getSingletonMutex();

}

2、AbstractBeanFactory源码实现

2.1 SimpleAliasRegistry源码

SimpleAliasRegistry:AliasRegistry接口的简单实现。作为BeanDefinitionRegistry实现的基类。
本类的实现整体逻辑比较简单。(该类主要完成别名到名称之间的映射。name一定要是canonical name)

public class SimpleAliasRegistry implements AliasRegistry {
   

	/** 日志,可用于子类 */
	protected final Log logger = LogFactory.getLog(getClass());

	/** 别名到真实bean名称的map */
	/** Map from alias to canonical name. */
	private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

	// 注册别名,保证alias同步
	@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) {
   
			if (alias.equals(name)) {
   
				// 此处直接删除,如果是别名到别名的映射有些不正确。如果是别名到 canonical 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;
					}
					if (!allowAliasOverriding()) {
   
						throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
								name + "': It is already registered for name '" + registeredName + "'.");
					}
				}
				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;
	}

	// 推断指定的name的bean是否有给定的别名
	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);
			}
		});
	}

	// 解析别名和原始名,可用于placeholders解析
	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);
				}
			});
		}
	}

	// 检查给定的名称是否已经指向给定的别名作为另一个方向的别名,在前面捕获循环引用并抛出相应的IllegalStateException。
	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;
	}

}

2.2 DefaultSingletonBeanRegistry源码

共享bean实例的通用注册表,实现SingletonBeanRegistry。允许注册应该为注册中心的所有调用者共享的单例实例,这些实例通过bean名获得。
还支持在注册中心关闭时销毁DisposableBean实例的注册(它可能对应于也可能不对应于已注册的单例)。可以注册bean之间的依赖关系,以强制执行适当的关闭顺序。
该类主要用作BeanFactory实现的基类,分解出对单例bean实例的公共管理。注意,ConfigurableBeanFactory接口扩展了SingletonBeanRegistry接口。
请注意,与AbstractBeanFactory和DefaultListableBeanFactory(从它继承)不同,这个类既没有使用bean定义概念,也没有使用bean实例的特定创建过程。也可以作为要委托的内置helper。

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
   

	/** Maximum number of suppressed exceptions to preserve. */
	private static final int SUPPRESSED_EXCEPTIONS_LIMIT = 100;
	// 单例的三级缓存
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
	// 当前正在创建的单例,循环依赖
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));
	private final Set<String> inCreationCheckExclusions =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	private Set<Exception> suppressedExceptions;
	private boolean singletonsCurrentlyInDestruction = false;
	private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

	// 当前bean -> 当前bean容纳的bean集合
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
	// 当前bean -> 依赖当前bean的bean集合
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
	// 当前bean -> 当前bean依赖的bean集合
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
	
	// ...... 省略简单方法
	@Override
	@Nullable
	public Object getSingleton(String beanName) {
   
		return getSingleton(beanName, true);
	}
	// 常见的面试题,关于Spring 单例循环依赖的处理源码
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   
		// Quick check for existing instance without full singleton lock
		Object singletonObject = this.singletonObjects.get(beanName)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值