BeanDefinitionRegistry
Spring中BeanDefinition的注册接口,常见的实现有DefaultListableBeanFactory
和GenericApplicationContext
。看看它的接口清单:
public interface BeanDefinitionRegistry extends AliasRegistry {
// 往注册表中注册一个BeanDefinition实例
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
// 从注册表中移除带有该BeanName的BeanDefinition
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 通过beanName从注册表中获取BeanDefinition
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 判断当前是否已经注册了该beanName的BeanDefinition
boolean containsBeanDefinition(String beanName);
// 获取当前注册的所有BeanDefinition的Name
String[] getBeanDefinitionNames();
// 获取当前已注册的BeanDefinition数量
int getBeanDefinitionCount();
// beanName(标识)是否被占用
boolean isBeanNameInUse(String beanName);
}
UML
UML-
SimpleBeanDefinitionRegistry
:BeanDefinitionRegistry较为简单的实现,仅提供注册能力,不提供工厂级别的能力,可作为简单的例子提供给读者做test使用. -
DefaultListableBeanFactory
:Spring最早可以独立运行的工厂类,不仅有容器注册功能,还是一个功能健全的Bean工厂。 -
GenericApplicationContext
:Spring通用上下文,需要较多的自定义实现。
DefaultListableBeanFactory的注册功能
前程回顾
上文中提到,BeanDefinitionReader在调用完
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
后,会调用BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
方法对该BeanDefinition进行注册.
DefaultListableBeanFactory
会将注册后的BeanDefinition放到一个ConcurrentHashMap的Map中进行存储,Key为beanName,Value为BeanDefinition。
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
注册的入口
这里传入了两个参数,bdHolder为BeanDefinition的包装器,getReaderContext().getRegistry()为DefaultListableBeanFactory。为什么是DefaultListableBeanFactory?因为Spring在实例化XmlBeanDefinitionReader的时候将容器本身作为参数进行了传递,这在设计模式上也可以称为委托。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
DefaultListableBeanFactory的多职能
DefaultListableBeanFactory
本身不仅作为工厂使用,而且还可以用作注册器,资源加载器。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
// 这里就是委托的体现,将DefaultListableBeanFactory作为构造参数传入了XmlBeanDefinitionReader中
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
进入到构造函数中,发现DefaultListableBeanFactory在这里已经充当了registry的职能了.
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
}
注册器实例
注册BeanDefinition-注册name和aliases
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
// 向容器注入BeanDefinition的名称和BeanDefinition本身
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
// 如果该BeanDefinition存在别名,再对别名进行注册
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
DefaultListableBeanFactory#registerBeanDefinition
注意,这里已经到达了DefaultLististableBeanFactory的registerBeanDefinition中了,上面的registry指向的是DefaultLististableBeanFactory.这里梳理一下主要的逻辑
- 判断是否为AbstractBeanDefinition的实例,如果是,校验该BeanDefinition是否有声明需要overrides的方法,如果有,创建代理类进行代理。
- 从
beanDefinitionMap
中尝试获取该beanName的BeanDefinition.
- 从
- 如果
beanDefinitionMap
已经有了,检测是否允许BeanDefinition覆盖。如果允许,则用put进行更新操作.
- 如果
- 如果从
beanDefinitionMap
获取不到,证明是新的BeanDefinition,查看工厂的bean是否进入已创建的阶段了,如果是,则证明是动态注册bean的方式.使用synchronized
对beanDefinitionMap
上锁,让进行put
操作,再依次更新beanDefinitionNames
和从manualSingletonNames
(手动注册单例的名称列表,按注册顺序。)中将该beanName移除
- 如果从
- 如果该BeanDefinition已存在,并且在单例缓存中,那么进行
resetBeanDefinition
,这是一个递归的过程,主要的工作是:清除合并的BeanDefinition缓存,从单例缓存中将该BeanName移除,通知处理器进行reset操作.
- 如果该BeanDefinition已存在,并且在单例缓存中,那么进行
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");
// 判断该beanDefinition是否为AbstractBeanDefinition的实例
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
// 校验look up 和 replace method 是否存在并且参数合法,如果存在,对该BeanDefinition进一步处理
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 从注册表中获取该BeanDefinition实例
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
// 是否允许BeanDefinition覆盖,容器配置
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
// 将beanName作为key,BeanDefinition作为value,放到容器map中
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 是否开始创建bean实例,如果已经有该实例,那么本次为动态的形式
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
// 锁住注册表
synchronized (this.beanDefinitionMap) {
// 更新beanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 创建一个长度为beanDefinitionNames+1的列表
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
// 先将存量的beanDefinitionName存储
updatedDefinitions.addAll(this.beanDefinitionNames);
// 再存储增量的beanName,顺序存储
updatedDefinitions.add(beanName);
// 更新整个BeanDefinitionNames
this.beanDefinitionNames = updatedDefinitions;
// 从单例BeanName列表中移除该beanName,如果this.manualSingletonNames中contains该beanName,执行remove操作
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
// 启动阶段
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
// 将注册期间冻结的beanName列表清除,一个volatile修饰的String数组,Spring内存优化操作
this.frozenBeanDefinitionNames = null;
}
// 检测是否存在该BeanDefinition且存在于IOC中
if (existingDefinition != null || containsSingleton(beanName)) {
// 重置注册的BeanDefinition缓存
// 包括BeanDefinition的父类以及合并的BeanDefinition缓存,即mergeBeanDefinition
// Spring会把有parent属性的Bean属性进行合并
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
DefaultListableBeanFactory#resetBeanDefinition
protected void resetBeanDefinition(String beanName) {
// Remove the merged bean definition for the given bean, if already created.
// 如果该beanName发生过merge操作,remove已经合并出的beanDefinition
clearMergedBeanDefinition(beanName);
// Remove corresponding bean from singleton cache, if any. Shouldn't usually
// be necessary, rather just meant for overriding a context's default beans
// (e.g. the default StaticMessageSource in a StaticApplicationContext).
// 从单例缓存中remove该beanName
destroySingleton(beanName);
// Notify all post-processors that the specified bean definition has been reset.
// 通知MergedBeanDefinitionPostProcessor,这个特殊的beanDefinition已经进行了重置
for (BeanPostProcessor processor : getBeanPostProcessors()) {
if (processor instanceof MergedBeanDefinitionPostProcessor) {
((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
}
}
// Reset all bean definitions that have the given bean as parent (recursively).
// 找出容器中与当前beanName不相同的bd,查看paretName是否跟当前beanName相同。
// 即父bean被清除了,子bean也应该要重置
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
BeanDefinition bd = this.beanDefinitionMap.get(bdName);
// Ensure bd is non-null due to potential concurrent modification
// of the beanDefinitionMap.
if (bd != null && beanName.equals(bd.getParentName())) {
// 递归调用,如果该bean还有子bean,继续进行清除
resetBeanDefinition(bdName);
}
}
}
}
流程图
Registry总结
- BeanDefinition的注册具体表现为往
DefaultListableBeanFactory
中的beanDefinitionMap
中添加一个BeanDefinition. - BeanDefinitionReader将注册功能委托给了
DefaultListableBeanFactory
进行注册.该注册器在初始化的时候进行了构造注入. - 在注册期间,Spring会校验是否允许BeanDefinition覆盖.
- Spring支持在工厂创建Bean实例后进行动态注册BeanDefinition.
网友评论