一、@ConditionalOnBean、@ConditionalOnProperty、@ConditionalOnClass

@ConditionalOnBean是指当spring容器中有某个bean时才装配。@ConditionalOnMissingBean当spring容器中不存在某个bean时才装配

@ConditionalOnClass是指当classpath下有某个类时才装配。@ConditionalOnMissingClass是指当classpath下没有某个类时才装配

@ConditionalOnProperty是指当某个配置项为某个值时才装配。@ConditionalOnMissingProperty是指当某个配置项不等于某个值时才装配

例如:@ConditionalOnBean(name="user")表示当容器中有名字为user的bean时才装配。

下面做下验证测试:

第一步:当没有任何注解时,spring容器里会有三个Runnable类型的bean,名字分别为createRable1,createRable2,createRable3

package com.lsl;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;

@SpringBootConfiguration
public class MyConfig {

    @Bean
    public Runnable createRable1(){
        System.out.println("=======default======");
        return ()->{};
    }

    @Bean
    public Runnable createRable2(){
        System.out.println("=======dev======");
        return ()->{};
    }

    @Bean
    public Runnable createRable3(){
        System.out.println("=======user======");
        return ()->{};
    }
}
package com.lsl;

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

@SpringBootApplication
public class SpringbootProviderApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext content = SpringApplication.run(SpringbootProviderApplication.class, args);
        System.out.println("springname=" + content.getEnvironment().getProperty("springboot.name"));
        System.out.println("ds.name="  + content.getEnvironment().getProperty("ds.name"));
        System.out.println("ds.password="  + content.getEnvironment().getProperty("ds.password"));

        //从容器中获取类型为Runnable的所有bean
        System.out.println(content.getBeansOfType(Runnable.class));
    }

}

 输出结果:

第二步:当分别加上注解时

package com.lsl;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;

@SpringBootConfiguration
public class MyConfig {

    @Bean
    @ConditionalOnBean(name="user")
    public Runnable createRable1(){
        System.out.println("=======default======");
        return ()->{};
    }

    @Bean
    @ConditionalOnClass(name="user")
    public Runnable createRable2(){
        System.out.println("=======dev======");
        return ()->{};
    }

    @Bean
    @ConditionalOnProperty(name="opFlag",havingValue = "save")
    public Runnable createRable3(){
        System.out.println("=======user======");
        return ()->{};
    }
}

结果输出:由于没有user的bean所以没有装配

第三步:创建User类,并交给spring容器托管。

package com.lsl;

import org.springframework.stereotype.Component;

@Component
public class User {
}

输出结果:由于spring容器托管了User类,名字且为user,所以createRable1装配了

在默认配置文件加上配置项 ,createRable3也装配了

 

由于classpath下没有user的bean,所有createRable2没有被装配。

二、@Conditional和Condition接口

上面的三个注解时spring提供的比较常用的几个注解,当然spring还提供了其他类似注解,

比如@ConditionalOnJava,当jdk为某个版本时才装配。

除此之外spring还提供了扩展,利用Condition接口和@Conditional注解自定义扩展功能

一般情况下Condition接口和@Conditional注解要配合使用。

首先是实现Condition接口。

package com.lsl;

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

import java.util.Arrays;
import java.util.List;

public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String opFlag = conditionContext.getEnvironment().getProperty("opFlag");
        String[] beanDefinitionNames = conditionContext.getRegistry().getBeanDefinitionNames();
        List<String> strings = Arrays.asList(beanDefinitionNames);
        if (strings.contains("user" ) && "save".equals(opFlag)){
            return true;
        }
        return false;
    }
}

createRable4()方法上加了 @Conditional(MyCondition.class)注解,表示只有当MyCondition中的方法返回true时才装配。

package com.lsl;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;

@SpringBootConfiguration
public class MyConfig {

    @Bean
    @ConditionalOnBean(name="user")
    public Runnable createRable1(){
        System.out.println("=======default======");
        return ()->{};
    }

    @Bean
    @ConditionalOnClass(name="user")
    public Runnable createRable2(){
        System.out.println("=======dev======");
        return ()->{};
    }

    @Bean
    @ConditionalOnProperty(name="opFlag",havingValue = "save")
    public Runnable createRable3(){
        System.out.println("=======user======");
        return ()->{};
    }

    @Bean
    @Conditional(MyCondition.class)
    public Runnable createRable4(){
        System.out.println("=======MyCondition======");
        return ()->{};
    }
}

 

输出结果如下:MyCondition的功能是当配置项opFlag=save且容器中已经注册了user名字的bean时才返回true

 

 这种配合使用的方法非常灵活,可以多看看Condition接口中matchs方法的两个参数,这2个参数能获取好多信息,可以根据信息进行相关逻辑判断是返回true还是false.

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐