springboot条件加载Bean-@Conditional

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

EncodingConvert 接口:

package com.xi.springbootdemo.conditional;

public interface EncodingConvert {
}

GBKEncodingConvert 实现类:

package com.xi.springbootdemo.conditional;

public class GBKEncodingConvert implements EncodingConvert{
}

UTF8EncodingConvert 实现类:

package com.xi.springbootdemo.conditional;

public class UTF8EncodingConvert implements EncodingConvert{
}

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

package com.xi.springbootdemo.conditional;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EncodingConvertConfiguration {

    @Bean
    public EncodingConvert createGBKEncodingConvert(){
        return new GBKEncodingConvert();
    }

    @Bean
    public EncodingConvert createUTF8EncodingConvert(){
        return new UTF8EncodingConvert();
    }
}

启动类:

package com.xi.springbootdemo.conditional;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
public 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.xi.springbootdemo.conditional.GBKEncodingConvert@9255c05, createUTF8EncodingConvert=com.xi.springbootdemo.conditional.UTF8EncodingConvert@5da7cee2}

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

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

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

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

package com.xi.springbootdemo.conditional;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class GBKCondition implements Condition {
    /*判断编码方式是否为gbk*/
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String encoding = System.getProperty("file.encoding");
        if(encoding != null){
            return "UTF-8".equals(encoding.toLowerCase());
        }
        return false;
    }
}

同理,UTF8EncodingConvert的条件类UTF8Condition 为:

package com.xi.springbootdemo.conditional;

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.xi.springbootdemo.conditional;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EncodingConvertConfiguration {

    @Bean
//    判断条件
    @Conditional(GBKCondition.class)
    public EncodingConvert createGBKEncodingConvert(){
        return new GBKEncodingConvert();
    }

    @Bean
    @Conditional(UTF8Condition.class)
    public EncodingConvert createUTF8EncodingConvert(){
        return new UTF8EncodingConvert();
    }
}

启动类为:

--UTF-8
{createUTF8EncodingConvert=com.xi.springbootdemo.conditional.UTF8EncodingConvert@3fae596}

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

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

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

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

package com.xi.springbootdemo.conditional;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
/*表示只要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();
    }
}

执行App输出如下:

--UTF-8
{createGBKEncodingConvert=com.xi.springbootdemo.conditional.GBKEncodingConvert@4a5905d9, createUTF8EncodingConvert=com.xi.springbootdemo.conditional.UTF8EncodingConvert@1a3e5f23}

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

package com.xi.springbootdemo.conditional;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
/*表示只要UTF8Condition中的match方法返回true时,就把GBKEncodingConvert和UTF8EncodingConvert的bean注入到IOC容器中*/
@Conditional({UTF8Condition.class,GBKCondition.class})
public class EncodingConvertConfiguration {

    @Bean
    public EncodingConvert createGBKEncodingConvert(){
        return new GBKEncodingConvert();
    }

    @Bean
    public EncodingConvert createUTF8EncodingConvert(){
        return new UTF8EncodingConvert();
    }
}

执行App输出如下:

--UTF-8
{}

四、其他注解

spring.factories文件里每一个xxxAutoConfiguration文件一般都会有下面的条件注解:

@ConditionalOnBean:当容器里有指定Bean的条件下

@ConditionalOnClass:当类路径下有指定类的条件下

@ConditionalOnExpression:基于SpEL表达式作为判断条件

@ConditionalOnJava:基于JV版本作为判断条件

@ConditionalOnJndi:在JNDI存在的条件下差在指定的位置

@ConditionalOnMissingBean:当容器里没有指定Bean的情况下

@ConditionalOnMissingClass:当类路径下没有指定类的条件下

@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下

@ConditionalOnProperty:指定的属性是否有指定的值

@ConditionalOnResource:类路径是否有指定的值

@ConditionalOnSingleCandidate:当指定Bean在容器中只有一个,或者虽然有多个但是指定首选Bean

@ConditionalOnWebApplication:当前项目是Web项目的条件下。

上面@ConditionalOnXXX都是组合@Conditional元注解,使用了不同的条件Condition

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Spring Boot 中,@Conditional 和 @AutoConfigureAfter 是两个常用的注解,它们分别用于控制 Bean 的条件和 Bean 的顺序。下面分别对它们进行解析。 ## @Conditional @Conditional 注解用于控制 Bean 的条件,即只有满足指定的条件时,才会该 Bean。它的作用类似于 Spring Framework 中的 @Profile 注解,但更为灵活。 @Conditional 注解可以标注在配置类上或者 Bean 定义方法上,用于控制配置类或者 Bean 的条件。它的参数是一个实现了 Condition 接口的类,该类需要实现 matches 方法,用于指定 Bean 条件。 下面是一个使用 @Conditional 注解的例子: ```java @Configuration @Conditional(MyCondition.class) public class MyConfig { @Bean public MyBean myBean() { return new MyBean(); } } ``` 这里,@Conditional(MyCondition.class) 指定了 MyConfig 配置类的条件,它的条件由 MyCondition 类中的 matches 方法指定。 ## @AutoConfigureAfter @AutoConfigureAfter 注解用于控制 Bean 的顺序,即指定在哪些 Bean 之后,才会当前 Bean。它的作用类似于 Spring Framework 中的 @DependsOn 注解,但更为灵活。 @AutoConfigureAfter 注解可以标注在配置类上或者 Bean 定义方法上,用于指定 Bean 的顺序。它的参数是一个字符串数组,指定了当前 Bean 依赖的其他 Bean 名称。 下面是一个使用 @AutoConfigureAfter 注解的例子: ```java @Configuration @AutoConfigureAfter({MyConfig1.class, MyConfig2.class}) public class MyConfig3 { @Bean public MyBean3 myBean3() { return new MyBean3(); } } ``` 这里,@AutoConfigureAfter({MyConfig1.class, MyConfig2.class}) 指定了在 MyConfig1 和 MyConfig2 配置类之后,才会 MyConfig3 配置类。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值