@Conditional注解使用及@ConditionalOnXXX各注解的作用
本文为博主原创,转载请注明 出处:
一。@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各注解的作用的更多相关文章
- spring boot @ConditionalOnxxx相关注解总结
Spring boot @ConditionalOnxxx相关注解总结 下面来介绍如何使用@Condition public class TestCondition implements Condit ...
- Spring注解开发之Spring常用注解
https://blog.csdn.net/Adrian_Dai/article/details/80287557主要的注解使用: 本文用的Spring源码是4.3.16@Configuration ...
- Android注解使用之通过annotationProcessor注解生成代码实现自己的ButterKnife框架
前言: Annotation注解在Android的开发中的使用越来越普遍,例如EventBus.ButterKnife.Dagger2等,之前使用注解的时候需要利用反射机制势必影响到运行效率及性能,直 ...
- [原创]java WEB学习笔记103:Spring学习---Spring Bean配置:基于注解的方式(基于注解配置bean,基于注解来装配bean的属性)
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- spring注解说明之Spring2.5 注解介绍(3.0通用)
spring注解说明之Spring2.5 注解介绍(3.0通用) 注册注解处理器 方式一:bean <bean class="org.springframework.beans.fac ...
- 深入理解Java:注解(Annotation)自定义注解入门
转载:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 元注解: 元注解的作用就是负责注解其他注解.Java5.0定义了4个标准 ...
- 【转】深入理解Java:注解(Annotation)自定义注解入门
http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 元注解: 元注解的作用就是负责注解其他注解.Java5.0定义了4个标准的me ...
- Java注解(Annotation)自定义注解入门
要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解: 元注解的作用就是负责注解其他注解.Java5. ...
- Java:注解(Annotation)自定义注解入门
转载地址:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的 ...
- spring mvc自定义注解--登录时密码加密注解
1,定义注解名称接口 /** * 使用该注解不用再MD5转换了 * * @author adonis * */ @Target(ElementType.PARAMETER) @Retention(Re ...
随机推荐
- Oracle-lsnrctl监听进程控制
LSNRCTL> help The following operations are available An asterisk (*) denotes a modifier or extend ...
- Scrapy如何在爬虫类中导入settings配置
假设我们在settings.py定义了一个IP地址池 ##### 自定义设置 IP_PROXY_POOL = ( "127.0.0.1:6789", "127.0.0.1 ...
- Ascii字符画 在线生成工具
英文 http://patorjk.com/software/taag/ 点击 Test All 一键测试所有样式 目前有317种可选 个人常用格式 3D-ASCII ANSI Shadow Bulb ...
- ElasticSearch之Open index API
打开指定的索引. 命令样例如下: curl -X POST "https://localhost:9200/testindex_003/_open?pretty" --cacert ...
- Python——第二章:字典(dictionary)以及 添、删、改、查
首先, 字典是以键值对的形式进行存储数据的,必须有键[key],有值[value] 字典的表示方式: {key:value, key2:value, key3:value} 举例: dic = {&q ...
- Linux的一些的常用命令
小杰笔记: 记录一下Linux的一些常见命令: 1:Linux关机与重启的命令: shutdown:关机 shutdown -h 30 30秒后关机 reboot 重启 sync:将数据由内存同步到硬 ...
- springboot整合hibernate(非JPA)(二)
springboot整合hibernate(非JPA)(二) springboot整合hibernate,非jpa,若是jpa就简单了,但是公司项目只有hibernate,并要求支持多数据库,因此记录 ...
- Next.js 开发指南 路由篇 | 动态路由、路由组、平行路由和拦截路由
前言 实际项目开发的时候,有的路由场景会比较复杂,比如数据库里的文章有很多,我们不可能一一去定义路由,此时该怎么办?组织代码的时候,有的路由是用于移动端,有的路由是用于 PC 端,该如何组织?如何有条 ...
- Flume快速入门
Flume快速入门 一.简介 高可用.高可靠,分布式的海量日志采集.聚合和传输系统,基于流式架构,灵活简单. event:事件 source:数据源 sink:目标 channel:数据管道 通过获取 ...
- 解读Java内存模型中Happens-Before的8个原则
摘要:本文我们就结合案例程序来说明Java内存模型中的Happens-Before原则. 本文分享自华为云社区<[高并发]一文秒懂Happens-Before原则>,作者: 冰 河. 在正 ...