引言
在上一篇文章中,我们大致介绍了Bean
创建、Bean
加载的流程,但是由于文章篇幅所限,不能事无巨细的进行详细介绍。后续本系列的文章将对这部分的内容进行庖丁解牛,尽可能的将IOC
中比较重要的细节说明清楚,以便于自己以及花时间阅读本文的读者可以加深对于Spring IOC
的深入理解。
BeanDefinition
BeanDefinitionRegistry
- 总结
一、BeanDefinition
纳尼,你还要说Spring IOC
,之前的文章你还没有说够嘛?
谁让Spring
中关于IOC
这部分的内容这么多呢,前面的文章还没有说的很细。所以只能继续慢慢往下唠叨了。废话不多说,我们来继续IOC
。
BeanDefinition
是用来描述Spring
中的Bean
,是包装Bean的数据结构。其源码如下所示:
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
//标准单例作用域的作用域标识符:“singleton”,对于扩展的bean工厂可能支持更多的作用域
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
//标准原型作用域的范围标识符:“prototype”
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
//表示BeanDefinition是应用程序主要部分的角色提示,通常对应于用户定义的bean
int ROLE_APPLICATION = 0;
//表示BeanDefinition是某些大型配置的支持部分的角色提示,通常是一个外部ComponentDefinition。
//当查看某个特定的ComponentDefinition时,认为bean非常重要,
//以便在查看应用程序的整体配置时能够意识到这一点
int ROLE_SUPPORT = 1;
//角色提示表明一个BeanDefinition是提供一个完全背景的角色,并且与最终用户没有关系。
//这个提示用于注册完全是ComponentDefinition内部工作的一部分的bean
int ROLE_INFRASTRUCTURE = 2;
//1、当前Bean父类名称
//如果父类存在,设置这个bean定义的父定义的名称
void setParentName(@Nullable String parentName);
//如果父类存在,则返回当前Bean的父类的名称
@Nullable
String getParentName();
//2、当前Bean的className
//指定此bean定义的bean类名称。
//类名称可以在bean factory后期处理中修改,通常用它的解析变体替换原来的类名称
void setBeanClassName(@Nullable String beanClassName);
//返回此bean定义的当前bean类名称
//需要注意的是,这不一定是在运行时使用的实际类名,以防子类定义覆盖/继承其父类的类名
//此外,这可能只是调用工厂方法的类,或者它 在调用方法的工厂bean引用的情况下甚至可能是空的
//因此,不要认为这是在运行时定义的bean类型,而只是将其用于在单独的bean定义级别进行解析
@Nullable
String getBeanClassName();
//3、bean作用域
//覆盖此bean的目标范围,指定一个新的范围名称
void setScope(@Nullable String scope);
//返回此bean的当前目标作用域的名称,如果没有确定,返回null
@Nullable
String getScope();
//懒加载
//设置这个bean是否应该被延迟初始化。如果{false},那么这个bean将在启动时由bean工厂实例化,
//这些工厂执行单例的立即初始化。
//懒加载 <bean lazy-init="true/false">
void setLazyInit(boolean lazyInit);
//返回这个bean是否应该被延迟初始化,即不是在启动时立即实例化。只适用于单例bean。
boolean isLazyInit();
//5.依赖关系设置
//设置这个bean依赖被初始化的bean的名字。 bean工厂将保证这些bean首先被初始化。
//<bean depends-on="">
void setDependsOn(@Nullable String... dependsOn);
//返回这个bean依赖的bean名称
@Nullable
String[] getDependsOn();
//6.是否是自动转配设置
//设置这个bean是否是获得自动装配到其他bean的候选人。
//需要注意是,此标志旨在仅影响基于类型的自动装配。
//它不会影响按名称的显式引用,即使指定的bean没有标记为autowire候选,也可以解决这个问题。
//因此,如果名称匹配,通过名称的自动装配将注入一个bean。
void setAutowireCandidate(boolean autowireCandidate);
//返回这个bean是否是自动装配到其他bean的候选者。就是是否在其他类中使用autowired来注入当前Bean的
//是否为被自动装配 <bean autowire-candidate="true/false">
boolean isAutowireCandidate();
//7.主候选Bean
//是否为主候选bean 使用注解:@Primary
void setPrimary(boolean primary);
//返回这个bean是否是主要的autowire候选者
boolean isPrimary();
//8.定义创建该Bean对象的工厂类
//指定要使用的工厂bean(如果有的话), 这是调用指定的工厂方法的bean的名称
void setFactoryBeanName(@Nullable String factoryBeanName);
//如果有返回工厂bean的名字
@Nullable
String getFactoryBeanName();
//9.创建该Bean对象的工厂方法
//如果有,指定工厂方法。这个方法先将通过构造函数参数被调用,或者如果参数,将调用该方法的无参数构造
void setFactoryMethodName(@Nullable String factoryMethodName);
//如果存在,返回工厂方法名
@Nullable
String getFactoryMethodName();
//10.返回此bean的构造函数参数值
//返回此bean的构造函数参数值
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
//11.获取属性
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
//12.设置初始方法
void setInitMethodName(@Nullable String initMethodName);
@Nullable
String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
@Nullable
String getDestroyMethodName();
void setRole(int role);
//13.当前Bean的角色
//获取这个bean的角色
int getRole();
void setDescription(@Nullable String description);
//14.可读描述
//返回对bean定义的可读描述
@Nullable
String getDescription();
//返回该bean定义来自的资源的描述
@Nullable
String getResourceDescription();
//返回原始的BeanDefinition;如果没有,则返回null。允许检索装饰的bean定义
@Nullable
BeanDefinition getOriginatingBeanDefinition();
//15.当前Bean的基本特性
//是否是单例的
boolean isSingleton();
//是否是多例的
boolean isPrototype();
//是否是抽象类
boolean isAbstract();
}
从上面的属性和方法分析可以看出,BeanDefinition
对于一个Bean
的描述做了比较完整的一套约束。这为后续的实现类提供了最基本的职责和属性。BeanDefinition
只是一个接口,它的具体实现如下所示:
二、BeanDefinitionRegistry
BeanDefinitionRegistry
继承了 AliasRegistry
接口,其核心子类有三个:SimpleBeanDefinitionRegistry
、DefaultListableBeanFactory
以及GenericApplicationContext
,类机构图如下所示:
AliasRegistry
作为 BeanDefinitionRegistry
的顶层接口,它的作用主要为别名管理的通用型接口, AliasRegistry
定义了一些别名管理的方法。
public interface AliasRegistry {
void registerAlias(String name, String alias);
void removeAlias(String alias);
boolean isAlias(String name);
String[] getAliases(String name);
}
BeanDefinitionRegistry
接口在实现AliasRegistry
之外还定义了关于 BeanDefinition
注册、注销、查询等一系列的操作。
public interface BeanDefinitionRegistry extends AliasRegistry {
// 向注册表中注册一个新的 BeanDefinition 实例
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
// 移除注册表中已注册的 BeanDefinition 实例
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 从注册中取得指定的 BeanDefinition 实例
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 判断 BeanDefinition 实例是否在注册表中(是否注册)
boolean containsBeanDefinition(String beanName);
// 取得注册表中所有 BeanDefinition 实例的 beanName(标识)
String[] getBeanDefinitionNames();
// 返回注册表中 BeanDefinition 实例的数量
int getBeanDefinitionCount();
// beanName(标识)是否被占用
boolean isBeanNameInUse(String beanName);
}
我们可以看下BeanDefinitionRegistry
的类实现结构如下所示:
这里关注下实现类GenericApplicationContext
,其中比较重要的方法为registerBeanDefinition
,它完成了BeanDefinition
的注册 :
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
...
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, 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) {
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 + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
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;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
其实上面这么多代码最重要的就是:
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
this.beanDefinitionMap.put(beanName, beanDefinition);
三、总结
本文主要介绍了BeanDefinition
以及BeanDefinition
的注册,BeanDefinition
是Spring
处理Bean
的统一的数据结构,BeanDefinitionRegistry
的实现类对BeanDefinition
完成了注册操作,注册最终结果保存在beanDefinitionMap
这个ConcurrentHashMap
中。今天的内容就到这里了,我们下次再会了哦。