1、什么是 BeanDefinitionRegistry ?

BeanDefinitionRegistry 可以根据字面意思去理解,它就是 BeanDefinition 的注册中心,负责管理IOC容器中的所有bean的定义信息;同时,它支撑其他组件实现动态注册Bean,如 ImportBeanDefinitionRegistrar,我们可实现 ImportBeanDefinitionRegistrar 接口,根据定制化需求往 BeanDefinitionRegistry 里面注册 Bean 信息,然后利用 @Import 注入从而定制化我们需要的Bean实例。

BeanDefinitionRegistry 的落地实现是 DefaultListableBeanFactory。

2、BeanDefinitionRegistry 的作用是什么?它的最终形态是什么?

BeanDefinitionRegistry 的作用是维护 BeanDefinition 的使用,它支持对 BeanDefinition 进行注册、修改和删除。

它的最终形态也就是上面提到的落地实现 DefaultListableBeanFactory。在 DefaultListableBeanFactory 的实现中,利用的是 JDK 自带的支持并发安全的 ConcurrentHashMap。详细看下面代码:

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

// .......
private final Map<String, BeanDefinition> beanDefinitionMap;

public DefaultListableBeanFactory() {

// ....
this.beanDefinitionMap = new ConcurrentHashMap(256);
// ....
}
// .......
}

3、BeanDefinition 与 BeanDefinitionRegistry 的关系是什么?

上面也提到了,BeanDefinitionRegistry 是 BeanDefinition 的注册中心,管理了IOC容器中的所有 Bean 的定义信息,支持对 BeanDefinition 进行注册、修改和删除操作。

4、动手实现借助 BeanDefinitionRegistry 注册移除 BeanDefinition。

4.1 添加-ImportBeanDefinitionRegistrar

实体类:

@Data
public class Person {
private String name;
}

@Data
public class Cat {
private Person person;
}

自定义ImportBeanDefinitionRegistrar,用于注册BeanDefinition:

public class CatImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
registry.registerBeanDefinition("myPerson",new RootBeanDefinition(Person.class));
registry.registerBeanDefinition("myCat", BeanDefinitionBuilder.genericBeanDefinition(Cat.class).addPropertyReference("person","myPerson").getBeanDefinition());
}
}

Java配置类,导入上面的组件:

@Configuration
@Import(CatImportBeanDefinitionRegistrar.class)
public class BeanConfiguration {
}

运行应用:

public class Application {

public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfiguration.class);
String[] beanNames = applicationContext.getBeanDefinitionNames();
for (String beanName : beanNames) {
System.out.println(beanName);
if (beanName.contains("Cat")){
Cat cat = (Cat) applicationContext.getBean(beanName);
System.out.println(cat);
}
if (beanName.contains("Person")){
Person person = (Person) applicationContext.getBean(beanName);
System.out.println(person);
}
}
}
}

运行结果:

// .....
org.springframework.context.event.internalEventListenerFactory
addBeanConfiguration
myPerson
Person(name=null)
myCat
Cat(person=Person(name=null))

4.2 删除-BeanFactoryPostProcessor

实体类的话还是沿用上面的两个,但是会利用自定义 BeanFactoryPostProcessor 来完成 BeanDefinition 的删除。

BeanFactoryPostProcessor:

@Component
public class CatBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) beanFactory;
// 遍历IOC容器中的所有BeanDefinition,如果 beanDefinitionName 带 Cat,则干掉
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
if (beanDefinitionName.contains("Cat")){
beanDefinitionRegistry.removeBeanDefinition(beanDefinitionName);
}
}
}
}

配置类:

@ComponentScan(basePackages = "com.github.howinfun.demo.ioc.bean_definition")
@Configuration
public class RemoveBeanDefinitionConfiguration {

@Bean
public Person myPerson(){
return new Person().setName("winfun");
}

@Bean
public Cat myCat(Person myPerson){
return new Cat().setPerson(myPerson);
}
}

应用:

public class Application {

public static void main(String[] args) {

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(RemoveBeanDefinitionConfiguration.class);
String[] beanNames = applicationContext.getBeanDefinitionNames();
for (String beanName : beanNames) {
System.out.println(beanName);
if (beanName.contains("Cat")){
Cat cat = (Cat) applicationContext.getBean(beanName);
System.out.println(cat);
}
if (beanName.contains("Person")){
Person person = (Person) applicationContext.getBean(beanName);
System.out.println(person);
}
}
}
}

运行结果:

// ......
removeBeanDefinitionConfiguration
catBeanFactoryPostProcessor
myPerson
Person(name=null)