3、条件加载Bean——@Conditional

来源:互联网 发布:淘宝长图 编辑:程序博客网 时间:2024/06/18 04:30

一、当用getBeansOfType从IOC容器中获取某种类型的bean时,若IOC容器中同时存在多于一个,则会把所有满足条件的bean都找出来。如下实例:创建一个接口EncodingConvert,创建该接口的两个实现类GBKEncodingConvert和UTF8EncodingConvert,并把两个实现类注入到IOC容器中,当从IOC容器中获取EncodingConvert类型的bean时,会同时获取到两个bean。代码如下:

EncodingConvert 接口:

package com.example.demo;public interface EncodingConvert {}

GBKEncodingConvert 实现类:

package com.example.demo;public class GBKEncodingConvert implements EncodingConvert {}

UTF8EncodingConvert 实现类:

package com.example.demo;public class UTF8EncodingConvert implements EncodingConvert {}

EncodingConvertConfiguration 配置类,用来把上面的两个实现类注入到IOC容器中:

package com.example.demo;import org.springframework.boot.SpringBootConfiguration;import org.springframework.context.annotation.Bean;@SpringBootConfigurationpublic class EncodingConvertConfiguration {    @Bean    public EncodingConvert createGBKEncodingConvert(){        return new GBKEncodingConvert();    }    @Bean    public EncodingConvert createUTF8EncodingConvert(){        return new UTF8EncodingConvert();    }}

启动类:

package com.example.demo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplicationpublic class App {    public static void main(String[] args) {        SpringApplication app = new SpringApplication(App.class);        ConfigurableApplicationContext context = app.run(args);        System.out.println(context.getBeansOfType(EncodingConvert.class));    }}

输出结果为:

{createGBKEncodingConvert=com.example.demo.GBKEncodingConvert@2438dcd, createUTF8EncodingConvert=com.example.demo.UTF8EncodingConvert@24105dc5}

从输出结果可以看出,同时或得了两个实现类的bean。

二、当IOC容器中有多于一个同类型的bean时,有时我们需要根据某种条件去选择加载其中的某个bean,此时可以通过@Conditional注解去条件化的加载某个bean。代码如下:

EncodingConvert 接口与GBKEncodingConvert实现类和UTF8EncodingConvert实现类代码相同。

下面定义加载GBKEncodingConvert类的条件类GBKCondition ,当类中的matches方法返回true时,就把GBKEncodingConvert的bean注入到IOC容器中(注入的时候还要用@Conditional来指定),反之,则不注入。
GBKCondition 类:

package com.example.demo;import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.type.AnnotatedTypeMetadata;public class GBKCondition implements Condition {    @Override    /*判断编码方式是否为gbk*/    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {        String encoding = System.getProperty("file.encoding");        if(encoding != null){            return "UTF-8".equals(encoding.toLowerCase());        }        return false;    }}

同理,UTF8EncodingConvert的条件类UTF8Condition 为:

package com.example.demo;import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.type.AnnotatedTypeMetadata;public class UTF8Condition implements Condition {    @Override    /*判断编码方式是否为utf-8*/    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {        String encoding = System.getProperty("file.encoding");        if(encoding != null){            return "utf-8".equals(encoding.toLowerCase());        }        return false;    }}

EncodingConvertConfiguration 配置类,用来把UTF8EncodingConvert和GBKEncodingConvert两个实现类根据@Conditional注解中的条件类进行注入bean。如果条件类中的matches方法为true,则把标注的bean注入到IOC容器中,反之不注入。

package com.example.demo;import org.springframework.boot.SpringBootConfiguration;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Conditional;@SpringBootConfigurationpublic class EncodingConvertConfiguration {    @Bean    /*判断条件*/    @Conditional(GBKCondition.class)    public EncodingConvert createGBKEncodingConvert(){        return new GBKEncodingConvert();    }    @Bean    @Conditional(UTF8Condition.class)    public EncodingConvert createUTF8EncodingConvert(){        return new UTF8EncodingConvert();    }}

启动类为:

package com.example.demo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplicationpublic class App {    public static void main(String[] args) {        SpringApplication app = new SpringApplication(App.class);        ConfigurableApplicationContext context = app.run(args);        /*获取当前的编码方式*/        System.out.println("--" + System.getProperty("file.encoding"));        System.out.println(context.getBeansOfType(EncodingConvert.class));    }}

运行启动类,输出:

--UTF-8{createUTF8EncodingConvert=com.example.demo.UTF8EncodingConvert@64b0598}

从结果可以看出,当前编码方式为UTF-8,所以只把UTF8EncodingConvert类的bean注入到了IOC容器中。

三、@Conditional注解的其它用法
1、@Conditional的注解不只用在方法上,还可以用在类上,这点从源码中可以看出:

/*@Target表明Conditional注解可以用在类或者方法上*/@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Conditional {    ......}

当@Conditional注解用在类上时,表示@Conditional中指定的条件返回true时,就把@Conditional注解标注类中的所有bean都注入到IOC容器中。

@SpringBootConfiguration/*表示只要UTF8Condition中的match方法返回true时,就把GBKEncodingConvert和UTF8EncodingConvert的bean注入到IOC容器中*/@Conditional(UTF8Condition.class)public class EncodingConvertConfiguration {    @Bean    public EncodingConvert createGBKEncodingConvert(){        return new GBKEncodingConvert();    }    @Bean    public EncodingConvert createUTF8EncodingConvert(){        return new UTF8EncodingConvert();    }}

2、可以在类上或者方法上用注解@Conditional标注时,可以同时指定多个条件类,表示多个条件同时返回true时,才会把标注的bean注入到容器中。例如:

@SpringBootConfiguration/*UTF8Condition和GBKCondition中条件方法都返回true时,才会把EncodingConvertConfiguration配置文件中的所有bean都注入到IOC容器中*/@Conditional({UTF8Condition.class, GBKCondition.class})public class EncodingConvertConfiguration {    @Bean    public EncodingConvert createGBKEncodingConvert(){        return new GBKEncodingConvert();    }    @Bean    public EncodingConvert createUTF8EncodingConvert(){        return new UTF8EncodingConvert();    }}