1.美图
2.概述
BeanDefinitionRegistry ,该类的作用主要是向注册表中注册 BeanDefinition 实例,完成 注册的过程。
BeanDefinitionRegistry 对象: 抽象出 bean 的注册逻辑。registerBeanDefinition、removeBeanDefinition、getBeanDefinition 等注册管理 BeanDefinition 的方法。
3.源码
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);
}
再来看它的继承关系:
4.DefaultListableBeanFactory
该类是 BeanDefinitionRegistry 接口的基本实现类,但同时也实现其他了接口的功能,这里只探究下其关于注册 BeanDefinition 实例的相关方法 。
首先来看它的成员变量:
// 关键-> 注册表,由 BeanDefinition 的标识 (beanName) 与其实例组成
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, bean>(64);
// 标识(beanName)集合
private final List<String> beanDefinitionNames = new ArrayList<String>(64);
再来看 BeanDefinitionReaderUtils
的 registerBeanDefinition
方法。该方法的主要作用是调用注册器(DefaultListableBeanFactory
)完成注册过程。
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 {
// BeanDefinition 校验
((AbstractBeanDefinition) beanDefinition).validate();
}catch (BeanDefinitionValidationException ex) {
// 抛出异常...
}
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
// 抛出异常...
}else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// 日志输出...
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
// 日志输出...
}
else {
// 日志输出...
}
}else {
// 添加标识进 List
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
this.frozenBeanDefinitionNames = null;
}
// 关键 -> 添加进 map
this.beanDefinitionMap.put(beanName, beanDefinition);
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
观察代码可以发现该方法最重要的步骤其实就是:
this.beanDefinitionMap.put(beanName, beanDefinition);
也就是向注册表中(beanDefinitionMap)添加 BeanDefinition 实例,完成注册的过程。
5.案例
5.1 自定义了一个BeanDefinitionRegistry
BeanDefinition实例化之后,会有"一个东西"将这些实例化的BeanDefinition交给BeanDefinitionRegistry并调用下面两个方法
public class MyBeanDefinitionRegistry implements BeanDefinitionRegistry {
//其他Override方法省略
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
System.out.println(String.format("调用方法:%s", "registerBeanDefinition"));
}
@Override
public boolean containsBeanDefinition(String beanName) {
System.out.println(String.format("调用方法:%s", "containsBeanDefinition"));
return false;
}
}
5.2 测试
package com.spring.boot.bean.registry;
import org.junit.Test;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import static org.junit.Assert.*;
public class MyBeanDefinitionRegistryTest {
/**
* 测试结果:
* 调用方法:containsBeanDefinition
* 调用方法:registerBeanDefinition
* 调用方法:containsBeanDefinition
* 调用方法:registerBeanDefinition
* 调用方法:containsBeanDefinition
* 调用方法:registerBeanDefinition
* 调用方法:containsBeanDefinition
* 调用方法:registerBeanDefinition
* 调用方法:containsBeanDefinition
* 调用方法:registerBeanDefinition
*/
@Test
public void registerBeanDefinition() {
MyBeanDefinitionRegistry myBeanDefinitionRegistry = new MyBeanDefinitionRegistry();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(myBeanDefinitionRegistry);
scanner.scan("com.spring.boot.bean.registry");
}
}
测试方法中的scanner就是我上面所说的"一个东西",我猜应该有很多类似这样的类,它会扫描基础包名下面所有有Company注解的类及其派生类,然后将这些类封装成BeanDefinition,每生成一个BeanDefinition,都会再将这个BeanDefinition交给我自己定义的MyBeanDefinitionRegistry方法,然后调用containsBeanDefinition方法,再调用registerBeanDefinition注册