1 BeanDefinition介绍
1.1 BeanDefinition
关于BeanDefinition介绍部分,参考自知乎的大神bravo1988,链接:https://www.zhihu.com/answer/723146648
BeanDeifinition实际上是生成bean之前的中间态,”假设Bean是红烧肉,那BeanDefinition就是该怎么做红烧肉“,也就是说,BeanDeifinition定义的是如何实例化bean这个过程。
BeanDefinition内部定义许多属性,但最常用实际上就下面几个:
- 懒加载:该bean是否实现懒加载?
- 单例/多例:该bean是单例还是多例?
- 初始化、销毁方法:定义该bean的初始化和销毁方法。
1.2 AnnotatedBeanDefinition
AnnotatedBeanDefinition是BeanDefinition的子接口,在Definition定义了bean的一些基本属性的基础上,还定义了两个Metadata:AnnotationMetadata和MethodMetadata。
public interface AnnotatedBeanDefinition extends BeanDefinition {
AnnotationMetadata getMetadata();
MethodMetadata getFactoryMethodMetadata();
}
MetaData称为元数据,指的是数据的数据,包括类名,方法名,注释名等等,详情请见我的博客:spring 之 元数据metadata:https://blog.csdn.net/bintoYu/article/details/104291098
2 BeanDefinition的注册
spring在初始化的过程中,会将BeanDefinition注册到内部中,下面会对其中的几个相关类进行介绍:
2.1 BeanDefinitionRegistry
BeanDefinitionRegistry是BeanDefinition的注册接口,也可以认为是BeanDefinition的存储接口,该接口定义了BeanDefinition的注册(增)、移除(删)、获得(查)的功能。
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String beanName);
}
2.2 SimpleBeanDefinitionRegistry
SimpleBeanDefinitionRegistry是BeanDefinitionRegistry的一个简单的实现类,使用名为beanDefinitionMap 的beanDefinitionMap来对BeanDefinition进行管理,但实际上很少会用到。
public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "'beanName' must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
this.beanDefinitionMap.put(beanName, beanDefinition);
}
...
2.3 DefaultListableBeanFactory
DefaultListableBeanFactory是最常用的BeanFactory,该类贯穿着整个spring体系中,有着许多的功能,其中一个就是对BeanDefinition进行管理,该类也实现了BeanDefinitionRegistry接口,本文只介绍与BeanDefinition相关的部分:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
//也以beanDefinitionMap作为容器
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
//按照注册顺序存放名称
private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
...进行一些判断
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 如果旧的不为null,说明这个beanName对应BeanDefinition已经存在
if (oldBeanDefinition != null) {
//判断是否允许覆盖(默认允许)
if (!isAllowBeanDefinitionOverriding()) {
//抛异常
}
// 若允许覆盖 那还得比较下role 如果新进来的这个Bean的role更大
// 比如老的是ROLE_APPLICATION:0 新的是ROLE_INFRASTRUCTURE:2
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
//打印一个warn日志提醒一下
}
...
//最终会将旧的替换掉
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//如果bean的创建阶段已经结束了,那么非线程安全的beanDefinitionNames和manualSingletonNames的处理方式便会有所不同,不是很重要
if (hasBeanCreationStarted()) {
//加个线程锁
synchronized (this.beanDefinitionMap) {
//添加到beanDefinitionMap和manualSingletonNames中
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
//manualSingletonNames移除该bean,不是很重要
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
@Override
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
// 移除整体上比较简单:beanDefinitionMap.remove
//从beanDefinitionMap中移除
BeanDefinition bd = this.beanDefinitionMap.remove(beanName);
// 若这个Bean定义本来就不存在,需要抛异常
if (bd == null) {
throw new NoSuchBeanDefinitionException(beanName);
}
//从beanDefinitionNames中移除
if (hasBeanCreationStarted()) {
synchronized (this.beanDefinitionMap) {
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames);
updatedDefinitions.remove(beanName);
this.beanDefinitionNames = updatedDefinitions;
}
} else {
this.beanDefinitionNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
resetBeanDefinition(beanName);
}
// 这个实现非常的简单,直接从map里拿
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}
}
2.4 GenericApplicationContext
BeanDefinitionRegistry真的是一个很神奇的接口,不仅作为BeanFactory的DefaultListableBeanFactory实现了它,作为spring容器ApplicationContext的GenericApplicationContext也实现了它。
实际上GenericApplicationContext并没有去重写BeanDefinitionRegistry的方法,而是内置了一个DefaultListableBeanFactory,借用DefaultListableBeanFactory来管理BeanDefinition。(有点适配器模式的味道,但应该不是适配器模式)
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
//内置了一个DefaultListableBeanFactory
private final DefaultListableBeanFactory beanFactory;
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
@Override
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
this.beanFactory.removeBeanDefinition(beanName);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
return this.beanFactory.getBeanDefinition(beanName);
}
}
2.5 AnnotationConfigApplicationContext
从类的声明上看,AnnotationConfigApplicationContext似乎并不属于BeanDefinitionRegistry接口:
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry
但实际上,我们看到AnnotationConfigApplicationContext继承了GenericApplicationContext,根据java的规范,子类是会继承父类的所有方法的,也就是说,Java中子类会继承父类对于接口的实现。
因此AnnotationConfigApplicationContext也能用于管理BeanDefinition。
至于为什么要讲到这个类,其实是为了给我的另一篇博客”spring 之 AnnotationConfigApplicationContext“提供帮助。
参考
怎么回答面试官:你对Spring的理解?
【小家Spring】Spring的Bean定义注册中心BeanDefinitionRegistry详解