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)