文章目录
1 BeanDefinitionRegistry
在之前的解析对象新建的时候,都需要接收一个BeanDefinitionRegistry类型的对象。BeanDefinitionRegistry是BeanDefinition注册的接口,提供注册需要的一些方法。实现了AliasRegistry别名注册接口。源码如下:
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
* @param beanName
* @param beanDefinition
* @throws BeanDefinitionStoreException if the BeanDefinition is invalid
* @throws BeanDefinitionOverrideException if there is already a BeanDefinition
* for the specified bean name and we are not allowed to override it
* @see GenericBeanDefinition
* @see RootBeanDefinition
* @see ChildBeanDefinition
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
/**
* 根据beanName移除BeanDefinition
* @param beanName the name of the bean instance to register
* @throws NoSuchBeanDefinitionException if there is no such bean definition
*/
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
/**
* 根据beanName获取BeanDefinition
* @param beanName name of the bean to find a definition for
* @return the BeanDefinition for the given name (never {@code null})
* @throws NoSuchBeanDefinitionException if there is no such bean definition
*/
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
/**
* 根据beanName检查是否包含BeanDefinition
* @param beanName the name of the bean to look for
* @return if this registry contains a bean definition with the given name
*/
boolean containsBeanDefinition(String beanName);
/**
* Return the names of all beans defined in this registry.
* @return the names of all beans defined in this registry,
* or an empty array if none defined
*/
String[] getBeanDefinitionNames();
/**
* Return the number of beans defined in the registry.
* @return the number of beans defined in the registry
*/
int getBeanDefinitionCount();
/**
* Determine whether the given bean name is already in use within this registry,
* i.e. whether there is a local bean or alias registered under this name.
* @param beanName the name to check
* @return whether the given bean name is already in use
*/
boolean isBeanNameInUse(String beanName);
}
那么BeanDefinitionRegistry的具体实现类是哪个呢?和我们之前追踪bean解析一样,参考上一篇0102Bean配置和解析-Bean生命周期-spring,我们可以追踪下BeanDefinition完成解析后,注册过程,看看使用了哪个实现类。
以AnnotatedBeanDefinitionReader解析注册为例,方法doRegisterBean()
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// 解析bean元信息为BeanDefinition对象
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// 省略
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// BeanDefinition注册
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
继续调用BeanDefinitionReaderUtils.registerBeanDefinition()方法,
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 注册
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
继续调用BeanDefinitionRegistry对象的registerBeanDefinition()方法,在BeanDefinitionRegistry的几个实现类中 ,SimpleBeanDefinitionRegistry只用于简单测试,GenericApplicationContext实际内部维护DefaultListableBeanFactory对象
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
// 省略
}
即我们可以认为DefaultListableBeanFactory是目前BeanDefinitionRegistry的唯一(?)实现类。
2 DefaultListableBeanFactory
想知道DefaultListableBeanFactory注册BeanDefinition都做了什么,这里我们了解下DefaultListableBeanFactor和BeanDefinition注册相关的部分内部相关结构。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** 是否允许覆盖 */
private boolean allowBeanDefinitionOverriding = true;
/** beanName-BeanDefinition 键值对的map */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** beanName List集合 */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
/** 手动注册单例beanName Set集合 */
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);
// 省略
}
- DefaultListableBeanFactory同时(间接)实现了BeanFactory和BeanDefinitionRegistry接口。
3 BeanDefinitionRegistry注册BeanDefinition都做了什么
上面追踪过程中,BeanDefinitionReaderUtils.registerBeanDefinition()方法第一部分完成BeanDefinition的注册,第二部分完成别名注册。
3.1 注册BeanDefinition
核心过程调用DefaultListableBeanFactory的registerBeanDefinition()方法完成,源代码如下:
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
// 校验
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
// 省略
// beanDefinitionMap已经存在同名beanName BeanDefinition定义,覆盖
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// 如果Bean已经开始创建,为了迭代稳定,不能修改用于创建Bean的集合
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
主要执行流程:
-
beanDefinitionMap根据beanName获取BeanDefinition对象existingDefinition
-
如果existingDefinition不为空,说明已经注册过
- 执行覆盖操作,不详述
-
否则是首次注册
-
判断hasBeanCreationStarted(),即是否已经开始创建Bean
- 如果已经开始创建Bean,那么相关的集合不能修改
- 执行最终3步
-
否则
- 执行最终3步
注册BeanDefinition最终的3步就是:
-
-
把beanName-BeanDefinition键值对放入beanDefinitionMap
-
把beanName放入beanDefinitionNames
-
removeManualSingletonName中移除beanName,如果有的话
3.2 注册别名
别名注册最后会调用SimpleAliasRegistry类的registerAlias方法
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) {
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);
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 + "'.");
}
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 + "'");
}
}
}
}
把name-alias键值对放入map。
BeanDefinitionRegistry注册BeanDefinition,最终就是把相关信息放入各自集合中,并不会创建Bean。
后记
❓QQ:806797785
⭐️源代码仓库地址:https://gitee.com/gaogzhen/spring6-study
参考:
[1]Spring系列之Bean生命周期详解[CP/OL].