一、是什么?
查看接口注释:根据给定的注释元数据,根据需要注册bean定义......spring会遍历所有的beanDefinition,逐个创建对应的bean。
public interface ImportBeanDefinitionRegistrar {
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassMetadata, registry);
}
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
PS:创建bean还有哪些方式?
1、@Component、@Bean等等
2、@Import(导入类)
3、实现ImportSelector接口,重写selectImports方法,返回需要导入的全类名
4、实现ImportBeanDefinitionRegistrar接口,注册bean定义
二、demo案例
StudentBean:学生类。
public class StudentBean {
private String stuName;
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
}
StudentImportBeanDefinitionRegistrar:实现ImportBeanDefinitionRegistrar接口。
@Component
public class StudentImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 创建beanDefinitionBuilder
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(StudentBean.class);
beanDefinitionBuilder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
// 获取beanDefinition
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(beanDefinition, StudentBean.class.getSimpleName());
// 注册beanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(beanDefinitionHolder, registry);
}
}
启动类:使用@Import导入StudentImportBeanDefinitionRegistrar类。
@Import(StudentImportBeanDefinitionRegistrar.class)
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
StudentBean studentBean = applicationContext.getBean(StudentBean.class);
System.out.println("studentBean: " + studentBean);
}
}
我们大都习惯使用@Enable***方式引入某个组件,此处可稍作改造。
新增注解:EnableStudentBean。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(StudentImportBeanDefinitionRegistrar.class)
public @interface EnableStudentBean {
}
启动类修改:
@EnableStudentBean
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
StudentBean studentBean = applicationContext.getBean(StudentBean.class);
System.out.println("studentBean: " + studentBean);
}
}
三、ImportBeanDefinitionRegistrar在其他开源项目中的使用
mybatis
在使用mybatis时,我们需要指定mapper的扫描路径:
@MapperScan(basePackages = "com.test.demo.dao.mapper")
查看@MapperScan源码,发现导入了MapperScannerRegistrar类,该类实现了ImportBeanDefinitionRegistrar接口。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
@Repeatable(MapperScans.class)
public @interface MapperScan
MapperScannerRegistrar类(截取部分代码):
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 获取MapperScan注解
AnnotationAttributes mapperScanAttrs = AnnotationAttributes
.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
if (mapperScanAttrs != null) {
// 扫描对应的mapper接口,并注册BeanDefinition(bean定义)
registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry,
generateBaseBeanName(importingClassMetadata, 0));
}
}
}
Openfeign
在使用OpenFeign时,我们需要指定feign接口扫描路径:
@EnableFeignClients(basePackages = ""com.test.demo")
查看@EnableFeignClients源码,发现导入了FeignClientsRegistrar类,该类实现了ImportBeanDefinitionRegistrar接口。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients
FeignClientsRegistrar类(截取部分代码):
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {
registerDefaultConfiguration(metadata, registry);
registerFeignClients(metadata, registry);
}
}
扫描所有加了@FeignClient注解的接口,接着注册FeignClientFactoryBean类型的BeanDefinition到容器中,需要使用时生成具体的接口代理实现服务调用。