1.ImportBeanDefinitionRegistrar接口的简要介绍
public interface ImportBeanDefinitionRegistrar {
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassMetadata, registry);
}
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
ImportBeanDefinitionRegistrar本质上是一个接口。在ImportBeanDefinitionRegistrar接口中,有registerBeanDefinitions()方法,通过该方法,我们可以向Spring容器中注册bean实例。
Spring官方在动态注册bean时,大部分套路其实是使用ImportBeanDefinitionRegistrar接口。
所有实现了该接口的类都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口,所以ImportBeanDefinitionRegistrar中动态注册的bean是优先于依赖其的bean初始化的,也能被aop、validator等机制处理。
2.使用方法
ImportBeanDefinitionRegistrar需要配合@Configuration和@Import这俩注解,其中,@Configuration注解定义Java格式的Spring配置文件,@Import注解导入实现了ImportBeanDefinitionRegistrar接口的类。
创建一个MyImportBeanDefinitionRegistrar类,去实现ImportBeanDefinitionRegistrar接口,如下所示。
package com.tianxia.springannotation.config.configImport;
import com.tianxia.springannotation.entity.RainBow;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* ImportBeanDefinitionRegistrar接口实例
* @author liqb
* @date 2023-04-24 10:45
**/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* 手动注册所有需要添加到容器中的bean
* @author liqb
* @date 2023-04-24 10:58
* @param annotationMetadata 当前类的注解信息
* @param registry BeanDefinition注册类
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("com.tianxia.springannotation.entity.Red");
boolean definition2 = registry.containsBeanDefinition("com.tianxia.springannotation.entity.Bule");
if (definition && definition2) {
// 指定bean的定义信息,包括bean的类型、作用域等等
// RootBeanDefinition是BeanDefinition接口的一个实现类
RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class); // bean的定义信息
// 注册一个bean,并且指定bean的名称
registry.registerBeanDefinition("rainBow", beanDefinition);
}
}
}
在配置类上的@Import注解中,添加MyImportBeanDefinitionRegistrar类,如下所示。
package com.tianxia.springannotation.config;
import com.tianxia.springannotation.config.configEntity.CustomerScope;
import com.tianxia.springannotation.config.configImport.MyImportBeanDefinitionRegistrar;
import com.tianxia.springannotation.config.configImport.MyImportSelector;
import com.tianxia.springannotation.entity.Color;
import com.tianxia.springannotation.entity.Person;
import com.tianxia.springannotation.entity.Red;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Scope;
/**
* 配置类
* @author liqb
* @date 2023-04-23 10:45
**/
@Configuration
// @Import快速地导入组件,id默认是组件的全类名
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig03 {
/**
* 创建person实例
* @author liqb
* @date 2023-04-23 09:46
* @return
*/
@Bean("person03")
@Scope(CustomerScope.CUSTOMER_SCOPE)
public Person person() {
System.out.println("给容器中添加咱们这个Person对象...");
return new Person("liqb", 24);
}
}
创建一个RainBow类,作为测试ImportBeanDefinitionRegistrar接口的bean来使用,如下所示
package com.tianxia.springannotation.entity;
/**
* 彩虹类
* @author liqb
* @date 2023-04-24 11:02
**/
public class RainBow {
}
调用测试方法,输出的结果信息如下所示: