本文为博主原创,转载请注明 出处:

一。@Conditional注解作用:

    必须是 @Conditional 注解指定的条件成立,才会在容器中添加组件,配置类里面的所有配置才会生效

二。@Conditional 衍生注解

@Conditional扩展注解作用 判断是否满足指定条件
@ConditionalOnBean 容器中存在指定Bean
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境

三。@Conditional注解 的使用

  3.1 @Conditional 注解源码解析

    @Conditional 注解源码:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}

    通过源码可以发现看到该注解的传参值 为一个数组,并且需要继承 Condition 类。

    查看 Condition 类的源码:

@FunctionalInterface
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}

    Condition 为一个函数式接口,其中只有一个matches 方法,接口的返回类型为boolean 值,通过该boolean 值控制是否加载配置。

  3.2 @Conditional  实现控制bean 加载

    1. 创建一个bean的实体类:

@Data
@AllArgsConstructor
public class Person { private String name; private int age;
}

    2. 通过 @Configuration 注解定义两个person 的bean

@Configuration
public class BeanConfiguration {
@Bean(name= "java")
public Person person1(){
return new Person("java",12);
}
@Bean(name= "linux")
public Person person2(){
return new Person("linux",22);
}
}

    3. 通过单元测试查看两个bean

@SpringBootTest
class TestApplicationTests {
@Autowired
private ApplicationContext applicationContext; @Test
void contextLoads() {
Map<String, Person> personBeanMap = applicationContext.getBeansOfType(Person.class);
personBeanMap.forEach((beanName, beanValue) -> {
System.out.println(beanName + "--" + beanValue);
});
}
}

    通过这个单元测试会打印出两行Person bean 的信息

    4. 定义 实现 Condition 接口的类,并控制是否加载。

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata; public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("linux")){
return true;
}
return false;
}
}

    并在定义Bean 的BeanConfiguration 类中使用 @Condition 注解实现bean 是否加载

import com.example.test.entity.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; @Configuration
public class BeanConfiguration { @Bean(name= "java")
public Person person1(){
return new Person("java",12);
} @Conditional(WindowsCondition.class)
@Bean(name= "linux")
public Person person2(){
return new Person("linux",22);
}
}

    5.执行单元测试:

import com.example.test.entity.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext; import java.util.Map; @SpringBootTest
class TestApplicationTests {
@Autowired
private ApplicationContext applicationContext; @Test
void contextLoads() {
Map<String, Person> personBeanMap = applicationContext.getBeansOfType(Person.class);
personBeanMap.forEach((beanName, beanValue) -> {
System.out.println(beanName + "--" + beanValue);
});
}
}

    运行之后只会打印 person1 这个bean 的信息。

四。@ConditionalOnProperty 注解的使用

    该注解经常用来管理配置文件中的某些配置开关,比如 中间件 通过这个配置判断是否进行加载。

   查看 @ConditionalOnProperty 注解源码

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional; @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({OnPropertyCondition.class})
public @interface ConditionalOnProperty {
String[] value() default {}; String prefix() default ""; String[] name() default {}; String havingValue() default ""; boolean matchIfMissing() default false;
}

    value : String数组 该属性与下面的 name 属性不可同时使用,当value所对应配置文件中的值为false时,注入不生效,不为fasle注入生效

    prefix  :配置文件中key的前缀,可与value 或 name 组合使用

     name  :与 value 作用一致

    havingValue  : 与value 或 name 组合使用,只有当value 或 name 对应的值与havingValue的值相同时,注入生效

    matchIfMissing  :该属性为true时,配置文件中缺少对应的value或name的对应的属性值,也会注入成功

    使用示例:

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration; @Configuration
@ConditionalOnProperty(prefix = "redis.config",value = "enabled",havingValue = "true")
public class RedisConfiguration {
}

    在application.yml 配置文件配置:

redis.config.enabled=true

    当 redis.config.enabled 值为 true时,会加载该类的配置,若只为false,则不加载。

    通过这种方式,可以很好的控制一些功能在不同环境上的开发性和使用性。

  

@Conditional注解使用及@ConditionalOnXXX各注解的作用的更多相关文章

  1. spring boot @ConditionalOnxxx相关注解总结

    Spring boot @ConditionalOnxxx相关注解总结 下面来介绍如何使用@Condition public class TestCondition implements Condit ...

  2. Spring注解开发之Spring常用注解

    https://blog.csdn.net/Adrian_Dai/article/details/80287557主要的注解使用: 本文用的Spring源码是4.3.16@Configuration ...

  3. Android注解使用之通过annotationProcessor注解生成代码实现自己的ButterKnife框架

    前言: Annotation注解在Android的开发中的使用越来越普遍,例如EventBus.ButterKnife.Dagger2等,之前使用注解的时候需要利用反射机制势必影响到运行效率及性能,直 ...

  4. [原创]java WEB学习笔记103:Spring学习---Spring Bean配置:基于注解的方式(基于注解配置bean,基于注解来装配bean的属性)

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  5. spring注解说明之Spring2.5 注解介绍(3.0通用)

    spring注解说明之Spring2.5 注解介绍(3.0通用) 注册注解处理器 方式一:bean <bean class="org.springframework.beans.fac ...

  6. 深入理解Java:注解(Annotation)自定义注解入门

    转载:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 元注解: 元注解的作用就是负责注解其他注解.Java5.0定义了4个标准 ...

  7. 【转】深入理解Java:注解(Annotation)自定义注解入门

    http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 元注解: 元注解的作用就是负责注解其他注解.Java5.0定义了4个标准的me ...

  8. Java注解(Annotation)自定义注解入门

    要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解: 元注解的作用就是负责注解其他注解.Java5. ...

  9. Java:注解(Annotation)自定义注解入门

    转载地址:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的 ...

  10. spring mvc自定义注解--登录时密码加密注解

    1,定义注解名称接口 /** * 使用该注解不用再MD5转换了 * * @author adonis * */ @Target(ElementType.PARAMETER) @Retention(Re ...

随机推荐

  1. Gradle构建微服务项目

    先说一下初衷把:为啥突然要用Gradle,公司后期自研项目都使用Gradle构建...... 1.下载安装 这个就不说了,网上大家搜索一下,配置一下环境变量即可 2.Groovy的一些语法Gradle ...

  2. SpringBoot CORS 跨域请求解决方案之配置过滤器

    方式一:@CrossOrigin 方式二: @Configuration public class CorsConfig implements WebMvcConfigurer { @Override ...

  3. docker 设计及源码分析

    1.dockerd 是一个长期运行的守护进程(docker daemon).负责管理 docker 容器的生命周期.镜像和存储等.实际还是通过grpc 的协议调用 containerd 的 api 接 ...

  4. 【C#】【IO】【实例】接上一个统计的新功能

    先用Python来创建多层级文件夹: import os root_path = r"C:\Users\Desktop\文案整理\Practice" for item in ran ...

  5. Kotlin委托属性(1)

    在Kotlin中,委托属性(Delegated Properties)是一种强大的语言特性,允许你将属性的 getter 和 setter 方法的实现委托给其他对象.这使得你能够通过委托来重用代码.将 ...

  6. javacv实现直播流

    javacv实现直播流 javacv从入门到入土系列,音视频入门有一点门槛的延迟大概是2~4秒之间, 依赖 <!-- 需要注意,javacv主要是一组API为主,还需要加入对应的实现 --> ...

  7. 动态规划问题(四)最长双音序列长度(LBS)

    问题描述 ​ 以一个乱序的数组,求它的最长双音序列长度.双音序列指该序列先递增,再递减. ​ 如: 对于序列 {1, 11, 2, 10, 4, 5, 2, 1},它的最长双音序列长度为 6, 对于序 ...

  8. 神经网络优化篇:详解指数加权平均数(Exponentially weighted averages)

    指数加权平均数 比如这儿有去年伦敦的每日温度,所以1月1号,温度是40华氏度,相当于4摄氏度.世界上大部分地区使用摄氏度,但是美国使用华氏度.在1月2号是9摄氏度等等.在年中的时候,一年365天,年中 ...

  9. 分布式机器学习的故事:Docker改变世界

    分布式机器学习的故事:Docker改变世界 Docker最近很火.Docker实现了"集装箱"--一种介于"软件包"和"虚拟机"之间的概念- ...

  10. 神经网络基础篇:关于 python_numpy 向量的说明(A note on python or numpy vectors)

    关于 python_numpy 向量的说明 主要讲Python中的numpy一维数组的特性,以及与行向量或列向量的区别.并说一下在实际应用中的一些小技巧,去避免在coding中由于这些特性而导致的bu ...