导入springboot_SpringBoot实战10-Spring基础-开启导入配置

接上篇《SpringBoot实战9-Spring基础-条件配置@Condtional》我们学习了条件注解@Conditonal的使用,本篇我们将学习开启注解@Enable*和导入注解@Import的使用。

c3c9d79ea47543f570bd63958f233f62.png

2.9 开启配置 - @Enable*和@Import

在后面的内容里会出现大量以@Enable*开头的注解,通过@Enable*将会自动对相应的功能进行自动配置。如:@EnableWebMvc、@EnableCaching、@EnableScheduling、@EnableAsync、@EnableWebSocket、EnableJpaRepositories、@EnableTransactionManagement、@EnableJpaAuditing、@EnableAspectJAutoProxy等。

而这开启配置的功能是由@Import注解提供的,@Import注解支持导入如下的配置:

  • 直接导入@Configuration配置类;
  • 配置类选择器ImportSelector的实现;
  • 动态注册器ImportBeanDefinitionRegistrar的实现。
  • 混合以上三种

下面我们将分别演示三种方式的实现:

2.9.1 直接导入@Configuration配置类

应用了注解了@Configuration都会被Spring Boot的默认组件扫描自动注册,所以我们将本节的注解类代码放入io.github.wiselyman.annotations包中,配置类的代码放入io.github.wiselyman.config中:

定义注解:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(AConfig.class) //直接导入配置类AConfig.classpublic @interface EnableA {}

定义配置类:

@Configurationpublic class AConfig {    @Bean    public String a(){        return "A";    }}

在JavaConfig中使用@EnableA注解,即可获得导入的配置类AConfig中的Bean a:

@EnableApublic class JavaConfig {}

在JavaConfig中使用CommandLineRunner执行:

@BeanCommandLineRunner enableAClr(String a){    return args -> System.out.println(a);}
577d9521a6cfb3a9f4e82f8f225b0428.png

2.9.2 配置类选择器ImportSelector的实现

在这个例子里,我们通过注解选择起效的配置类,注解定义如下:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(BSelector.class) public @interface EnableB {    boolean isUppercase() default true; //isUppercase是用来作为选择条件的}

在io.github.wiselyman.selector里定义选择器:

public class BSelector implements ImportSelector { //1    @Override    public String[] selectImports(AnnotationMetadata importingClassMetadata) { //2         AnnotationAttributes attributes =                AnnotationAttributes.fromMap(                        importingClassMetadata.getAnnotationAttributes                                (EnableB.class.getName(), false));         boolean isUppercase = attributes.getBoolean("isUppercase"); //3        if(isUppercase == true)             return new String[]{"io.github.wiselyman.config.BUppercaseConfig"}; //4        else            return new String[]{"io.github.wiselyman.config.BLowercaseConfig"}; //5    }}
  1. 选择器要实现ImportSelector接口;
  2. 实现接口的selectImports方法,参数AnnotationMetadata importClassMetadata是注解使用类(本例为JavaConfig)上@EnableB的元数据信息;
  3. 通过@EnableB在实际使用中的元数据,获得isUppercase的值;
  4. 如果isUppercase == true,此时实际使用时是@EnableB或者@EnableB(isUppercase = true)使用BUppercaseConfig提供的配置;
  5. 若实际使用时@EnableB(isUppercase = false)否则使用BLowercaseConfig提供的配置。

BUppercaseConfig的定义:

@Configurationpublic class BUppercaseConfig {    @Bean    public String b(){        return "B"; //返回一个大写B的Bean的配置    }}

BLowercaseConfig的定义:

@Configurationpublic class BLowercaseConfig {    @Bean    public String b(){        return "b"; //返回一个小写b的Bean的配置    }}

在JavaConfig中使用@EnableB,并用CommandLineRunner检验:

@EnableBpublic class JavaConfig {}
@BeanCommandLineRunner enbaleBClr(String b){    return args -> System.out.println(b);}
1529b4dfd845a1293a6427cf817582fd.png


若将isUppercase设置为false,如:

@EnableB(isUppercase = false)public class JavaConfig {}
d749f58ff946295d48c6b1077f66cd20.png

2.9.3 动态注册器ImportBeanDefinitionRegistrar的实现

本例通过ImportBeanDefinitionRegistrar可动态注册Bean到容器里。

注解定义:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(CBeanDefinitionRegistrar.class)public @interface EnableC {}

在io.github.wiselyman.registrar包中定义注册器:

public class CBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { //1    @Override    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, //2                                        BeanDefinitionRegistry registry) { //3        BeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(String.class) //4                                            .addConstructorArgValue("C") //5                                            .setScope(BeanDefinition.SCOPE_SINGLETON) //6                                            .getBeanDefinition(); //7       registry.registerBeanDefinition("c",bd); //8    }}
  1. 注册器需实现ImportBeanDefinitionRegistrar接口;
  2. 实现registerBeanDefinitions,参数AnnotationMetadata importClassMetadata是注解使用类(本例为JavaConfig)上@EnableB的元数据信息;
  3. 参数BeanDefinitionRegistry registry是用来注册所有Bean的定义的接口;
  4. 我们可以使用BeanDefinitionBuilder来编程式实现Bean的定义(BeanDefinition),此句定义了一个类型为String的Bean;
  5. 构造String的值是C;
  6. 设置Bean的Scope是singleton;
  7. 获得Bean的定义;
  8. 将Bean注册为名称为c的Bean。

此时我们在JavaConfig上使用@EnableC,并用CommandLineRunner检验:

@EnableCpublic class JavaConfig {}
@BeanCommandLineRunner enableCClr(String c){    return args -> System.out.println(c);}

静态注册的Bean,IntelliJ IDEA可以检测到,而动态注册的检测不到,所以这时候IDE会标红,但是正常运行:

6fab532f3ab2126f8020a5413cab733f.png
234cfbca9f3fa4e400ac1355eda351b1.png

2.9.4 混合使用

@Import支持导入配置类的数组,我们可以混合上面三种配置,如我们可以定义一个注解具备上面三个的功能:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import({AConfig.class, BForABCSelector.class, CBeanDefinitionRegistrar.class})public @interface EnableABC {    boolean isUppercase() default true;}

选择器里指定了使用的注解的类,所以要新建一个新选择器:

public class BForABCSelector implements ImportSelector {    @Override    public String[] selectImports(AnnotationMetadata importingClassMetadata) {        AnnotationAttributes attributes =                AnnotationAttributes.fromMap(                        importingClassMetadata.getAnnotationAttributes                                (EnableABC.class.getName(), false)); // 此处使用的是@EnableABC        boolean isUppercase = attributes.getBoolean("isUppercase");        if(isUppercase == true)            return new String[]{"io.github.wiselyman.config.BUppercaseConfig"};        else            return new String[]{"io.github.wiselyman.config.BLowercaseConfig"};    }}

我们在JavaConfig中启用@EnableABC并用CommandLineRunner检验:

@EnableABCpublic class JavaConfig {}
@BeanCommandLineRunner enableABCClr(String a, String b, String c){    return args -> {        System.out.println(a);        System.out.println(b);        System.out.println(c);    };}
e526e0685c6d720dd625a93df1bd94f6.png

下一篇《SpringBoot实战11-Spring基础-全局Bean处理BeanPostProcessor》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值