目录
3. ImportBeanDefinitionRegistrar
Spring学习专栏
3. Spring中@Conditional注解详细讲解及示例
一、概述
@Import注解的作用是给容器中导入组件,回顾下我们给容器中注入组件的方式,可以通过Spring的xml配置方式,也可以通过注解,如
@Component
等,也可以通过java配置类的方式给容器中导入注解,今天来介绍另一个注解,其作用也是给容器中导入组件。
二、案例详解
1. Import导入
1. 创建 Blue、Yellow 类
public class Blue {
}
public class Yellow {
}
2. 创建BeanConfig类
@Import({Blue.class,Yellow.class}) 将这两个类导入到容器中,id默认是组件的全类名
@Import({Blue.class, Yellow.class})
@Configuration
public class BeanConfig {
}
3. 创建ImportTest测试类
public class ImportTest {
private static AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
@Test
public void test1(){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
控制台打印结果输出
注意:BeanId为类的全路径
2. ImportSelector
上面可以看到 ,这种方式进行导入呢?还是略微麻烦了点,如果组件很多,也是比较麻烦的,所以呢,我们也可以结合ImportSelector来使用,首先,我们再写两个类,叫做Red.java
和 Green.java
,不必关心类里有什么,哪怕是个空类也是可以的,我们只关心其是否能被正确注入到组件之中
那如何使用ImportSelector
呢?
2. 创建MyImportSelector类
这是一个接口,继承并实现即可
/**
* 自定义逻辑返回需要导入的组件
* @date: 2021/2/25 18:15
*/
public class MyImportSelector implements ImportSelector {
/**
* 导入容器集合
* @param importingClassMetadata 当前标注@Import注解的类的所有注解信息
* @date: 2021/2/25 18:15
* @return: java.lang.String[] 返回值,就是到导入到容器中的组件全类名
*/
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.zlp.spring.v4.entity.Red","com.zlp.spring.v4.entity.Green"};
}
}
关于这个导入选择器,从这个方法名 selectImports
就可以看出,是选择性的导入的意思,所以在这个方法中,我们是可以通过编写不同的逻辑,来返回我们需要导入的组件,那上面自定义的选择导入器,只是为了演示,所以没有具体的条件判断等,可自行扩展,返回需要导入的组件Red
和Green
,然后将这个类加入到@Import
注解的参数中,如下代码
@Import({Blue.class, Yellow.class,MyImportSelector.class})
@Configuration
public class BeanConfig {
}
控制台打印结果输出
3. ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar
与ImportSelector
的使用大致相同,它是接口,我们只需实现它,并将它作为参数,放在@Import中即可。
1. 创建MyImportBeanDefinitionRegistrar
类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry: BeanDefinition注册类;
* 把所有需要添加到容器中的bean;调用
* BeanDefinitionRegistry.registerBeanDefinition手工注册进来
*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("com.zlp.spring.v4.entity.Red");
boolean definition2 = registry.containsBeanDefinition("com.zlp.spring.v4.entity.Blue");
if(definition && definition2){
//指定Bean定义信息;(Bean的类型,Bean。。。)
RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
//注册一个Bean,指定bean名
registry.registerBeanDefinition("rainBow", beanDefinition);
}
}
}
在BeanCofig配置类的@Import注解中加入这个自定义的类
@Import({Blue.class, Yellow.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
@Configuration
public class BeanConfig {
}
控制台打印结果输出
对比后两种注册方法,我们发现,ImportBeanDefinitionRegistrar是没有返回值的,另外它多了一个参数BeanDefinitionRegistry
,也就是可以直接在方法中就注册bean。
我们来看下ImportBeanDefinitionRegistrar的源码,
2. 源码分析
package org.springframework.context.annotation;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.type.AnnotationMetadata;
public interface ImportBeanDefinitionRegistrar {
/**
* Register bean definitions as necessary based on the given annotation metadata of
* the importing {@code @Configuration} class.
* <p>Note that {@link BeanDefinitionRegistryPostProcessor} types may <em>not</em> be
* registered here, due to lifecycle constraints related to {@code @Configuration}
* class processing.
* @param importingClassMetadata annotation metadata of the importing class
* @param registry current bean definition registry
*/
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
我们看下方法第一个参数AnnotationMetadata importingClassMetadata
,这个是注解的元信息,即配置类上所有注解的信息,然后可以MyImportBeanDefinitionRegistrar
自定义我们自己需要的逻辑,动态注册bean、
不同的是,这个类通过BeanDefinitionRegistry
本身就可以注册组件。
项目地址
https://gitee.com/gaibianzlp/spring-study-demo.git
参考文档