@Conditional注解详解

目录

一、@Conditional注解作用

 二、@Conditional源码解析

2.1 Conditional源码

2.2 Condition源码

三、Conditional案例

3.1 Conditional作用在类上案例

3.1.1 配置文件

3.1.2 Condition实现类

3.1.3 Bean内容类

3.1.4 Config类

3.1.5 Controller类

3.1.6 测试结果

3.2 Condition作用在类上且多个条件

3.2.1 增加一个Condition实现类

3.2.2 Config2类

3.3 @Conditional注入到方法上

3.3.1 Bean内容类

3.3.2 Condition实现类

3.3.3 Config配置类

3.3.4 Controller测试类

3.3.5 测试结果

 四、@Conditional系列注解拓展

4.1 @Component容器和@Bean容器的区别

4.2 @Conditonal注解拓展

4.2.1 @ConditionalOnClass

4.2.1.1 config类

4.2.1.2 Controller类

4.2.1.3  结果

4.2.2 @ConditionalOnMissingClass

4.2.2.1 Config

4.2.2.2 Controller

4.2.2.3 测试

4.2.3 @ConditionalOnBean

4.2.3.1 config

4.2.3.2 Controller

 4.2.3.3 测试结果

4.2.4 @ConditionalOnSingleCandidate

4.2.4.1 config

 4.2.4.2 Controller

 4.2.4.3 测试结果

4.2.5 @ConditionalOnWebApplication

4.2.5.1 config

4.2.5.2 Controller

 4.2.5.3 结果

4.2.6 @ConditionalOnProperty

4.2.6.1 yml文件内容

4.2.6.2 config

4.2.6.3 Contoller

4.2.6.4 测试结果


一、@Conditional注解作用

Conditional中文翻译是条件的意思,@Conditional注解的作用是按照一定的条件进行判断,满足条件给容器注册bean。

 二、@Conditional源码解析

2.1 Conditional源码

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

从源码中可以看到,@Conditional只有一个数组参数,也就是说明,传递的参数是可以多个的,但这个参数是要求继承Condition类。 

2.2 Condition源码

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

Condition是一个函数式接口,matches就是它的比较方法,如果为true,那么就注入,如果为false,则不注入

三、Conditional案例

3.1 Conditional作用在类上案例

3.1.1 配置文件

enable:flag: true

3.1.2 Condition实现类

public class TestCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {Environment environment = context.getEnvironment();String flagString = environment.getProperty("enable.flag");// 如果flagString为true,则直接返回trueif(Boolean.parseBoolean(flagString)){return true;}return false;}
}

3.1.3 Bean内容类

public class TestBean {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return name + "是TestBean";}
}

3.1.4 Config类

@Conditonal注解作用在类上,并且判断的条件只有一个

@Configuration
@Conditional(TestCondition.class)
public class TestConfig {@Beanpublic TestBean testBean(){TestBean testBean = new TestBean();testBean.setName("java");testBean.toString();return testBean;}
}

3.1.5 Controller类

controller用于测试

注意点:@Autowired注解后面建议加上required=false,这样就算Condition实现类(对应上面的TestCondition类)返回的结果为false,那么项目也不会启动报错,如果没有加上,当Condition实现类返回为false的时候,项目启动过程会报Field config in com.common.commonframework.TestController required a bean of type 'com.common.commonframework.TestConfig' that could not be found.错误

@RestController
public class TestController {//如果为false,启动的时候在这一步会报错,可以添加成@Autowired(required = false)private TestConfig config;@GetMapping("/test")public void printImportBeanInfo() {System.out.println(config);System.out.println(config.testBean());}}

3.1.6 测试结果

3.2 Condition作用在类上且多个条件

3.2.1 增加一个Condition实现类

public class TestCondition2 implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {//直接返回false,用于测试return false;}
}

3.2.2 Config2类

@Conditional多个条件

注意点:下面的代码由于TestConditon2知己诶返回的是false,所以是一定会注入失败的

// TestCondition为false,所以在这个地方是一定会注入失败的
@Configuration
@Conditional({TestCondition.class,TestCondition2.class})
public class TestConfig2 {@Beanpublic TestBean testBean(){return new TestBean();}
}

3.3 @Conditional注入到方法上

3.3.1 Bean内容类

public class TestBean2 {private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "测试方法Bean";}
}

3.3.2 Condition实现类

这个实现类直接返回结果直接为false,用于测试

public class TestCondition3 implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {return false;}
}

3.3.3 Config配置类

@Configuration
public class TestConfig3 {@Bean@Conditional({TestCondition3.class})public TestBean2 testBean3(){TestBean2 testBean2 = new TestBean2();testBean2.setAddress("上海");return  testBean2;}
}

3.3.4 Controller测试类

@RestController
public class TestController {@Autowiredprivate TestConfig3 config3;@GetMapping("/test")public void printImportBeanInfo() {//因为@Conditional修饰的是在方法上,,所以TestConfig3是会注入进去的System.out.println(config3);System.out.println(config3.testBean3());}
}

3.3.5 测试结果

由于在TestConfig3的方法上面修饰的@Conditonal注解返回的是false,所以我们在调用对应的Bean的时候会直接报"No bean named ''xx" available"错误

 四、@Conditional系列注解拓展

springboot提供的@Conditonal系列注解作用:对@Component,@Bean等容器注解进行校验。校验是否满足指定的条件,只有满足指定的条件时,才会将对应的内容放到容器里面。如果在启动过程当中,直接报了@Bean容器重复,那么建议直接用@Conditional注解处理。

4.1 @Component容器和@Bean容器的区别

@Component作用于类,@Bean作用于方法

@Component是通过路劲扫描的方式自动装配到bean容器中,而@Bean是将方法返回值作为bean自动装配到IOC容器中

@Bean功能比@Component的功能更加强大,当我们需要引用外部类,并需要将它注入到IOC容器时,@Component注解是做不到的,但@Bean可以做到。

4.2 @Conditonal注解拓展

4.2.1 @ConditionalOnClass

当给定的类名在类路径上存在,则实例化当前Bean

4.2.1.1 config类

TestBean2类在文章的上面

@Configuration
public class TestConfig4 {@Bean@ConditionalOnClass(TestBean2.class) //当TestBean2存在,那么这个bean就会注入到容器public TestBean2 testBean3(){TestBean2 testBean2 = new TestBean2();testBean2.setAddress("北京");return  testBean2;}@Bean@ConditionalOnClass(name = "com.common.commonframework.TestBean2") //也可以通过路径直接获取对应的类public TestBean2 testBean4(){TestBean2 testBean2 = new TestBean2();testBean2.setAddress("北京");return  testBean2;}
}
4.2.1.2 Controller类
@RestController
public class TestController {@Autowiredprivate TestConfig4 config4;@GetMapping("/test")public void printImportBeanInfo() {System.out.println(config4);System.out.println(config4.testBean3());System.out.println(config4.testBean4());}
}
4.2.1.3  结果

因为TestBean2这个类存在,所以成功注入

4.2.2 @ConditionalOnMissingClass

当给定的类名在类路径上不存在,则实例化当前Bean

4.2.2.1 Config
@Configuration
public class TestConfig5 {@Bean@ConditionalOnMissingClass({ "com.common.commonframework.TestBean2"}) // 如果不存在TestBean2这个类,就将Bean注入容器,目前存在,所以会失败public TestBean2 testBean3(){TestBean2 testBean2 = new TestBean2();testBean2.setAddress("北京");return  testBean2;}
}
4.2.2.2 Controller
@RestController
public class TestController {@Autowiredprivate TestConfig5 config5;@GetMapping("/test")public void printImportBeanInfo() {System.out.println(config5);System.out.println(config5.testBean3());}
}
4.2.2.3 测试

提示失败,因为TestBean2是存在的

4.2.3 @ConditionalOnBean

当给定的在bean存在时,则实例化当前Bean

4.2.3.1 config
@Configuration
public class TestConfig6 {@Beanpublic TestBean testBean(){TestBean testBean = new TestBean();testBean.setName("java");testBean.toString();return testBean;}@Bean@ConditionalOnBean(name = "testBean") //这个会成功,因为存在testBean这个容器public TestBean2 testBean3(){TestBean2 testBean2 = new TestBean2();testBean2.setAddress("北京");return  testBean2;}@Bean@ConditionalOnBean(name = "testBean2") //这个会失败,因为不存在testBean2这个Beanpublic TestBean2 testBean4(){TestBean2 testBean2 = new TestBean2();testBean2.setAddress("北京");return  testBean2;}
}
4.2.3.2 Controller
@RestController
public class TestController {@Autowiredprivate TestConfig6 config6;@GetMapping("/test")public void printImportBeanInfo() {System.out.println(config6);System.out.println(config6.testBean3());System.out.println(config6.testBean4());}
}
 4.2.3.3 测试结果

testBean3成功,testBean4失败

4.2.4 @ConditionalOnSingleCandidate

只有指定的类已存在于BeanFactroy容器中,且只有一个实例时,才会作为bean放到容器。如果有多个,则指定首选的bean。@ConditionalOnSingleCandidate是@ConditionalOnBean的一种情况,满足前者时一定满足后者,满足后者时不一定满足前者

4.2.4.1 config

下面的案例是自定义bean然后注入到BeanFactory之中,springboot实际上有很多bean在启动过程当中会自动注入BeanFactory,不需要我们手动再去注入BeanFactory,比如我们常用的RedisConnectionFactory等等

@Configuration
public class TestConfig7  implements InitializingBean, BeanFactoryAware {public ConfigurableListableBeanFactory beanFactory;@Bean@ConditionalOnSingleCandidate //自定义的bean注入了BeanFactory所以会成功public TestBean testBean(){TestBean testBean = new TestBean();testBean.setName("java");testBean.toString();return testBean;}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = (beanFactory instanceof ConfigurableListableBeanFactory)? (ConfigurableListableBeanFactory) beanFactory : null;}@Overridepublic void afterPropertiesSet() throws Exception {TestBean testBean = new TestBean();testBean.setName("java");testBean.toString();beanFactory.registerSingleton("testBean",testBean);}
}
 4.2.4.2 Controller
@RestController
public class TestController {@Autowiredprivate TestConfig7 config7;@GetMapping("/test")public void printImportBeanInfo() {System.out.println(config7);System.out.println(config7.testBean());}
}
 4.2.4.3 测试结果

4.2.5 @ConditionalOnWebApplication

指定对应的web应用类型,才会做为bean放到容器中

4.2.5.1 config
@Configuration
public class TestConfig8 {@Bean@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) //web应用类型是servlet应用就会注入beanpublic TestBean testBean(){TestBean testBean = new TestBean();testBean.setName("java");testBean.toString();return testBean;}@Bean@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) //web应用类型是reactive应用就会注入beanpublic TestBean testBean2(){TestBean testBean = new TestBean();testBean.setName("java");testBean.toString();return testBean;}
}
4.2.5.2 Controller
@RestController
public class TestController {@Autowiredprivate TestConfig8 config8;@GetMapping("/test")public void printImportBeanInfo() {System.out.println(config8);System.out.println(config8.testBean());System.out.println(config8.testBean2());}
}
 4.2.5.3 结果

从结果可以看到一个testBean成功,一个testBean2失败,因为我的应用类型是servlet

4.2.6 @ConditionalOnProperty

yml或者properties文件,只有当配置条件满足要求时,才会放到bean容器

4.2.6.1 yml文件内容
conditional:test: 1
4.2.6.2 config
@Configuration
public class TestConfig9 {@Bean@ConditionalOnProperty("conditional.test")public TestBean testBean(){TestBean testBean = new TestBean();testBean.setName("java");testBean.toString();return testBean;}@ConditionalOnProperty("conditional.test.test")@Beanpublic TestBean testBean2(){TestBean testBean = new TestBean();testBean.setName("java");testBean.toString();return testBean;}
}
4.2.6.3 Contoller
@RestController
public class TestController {@Autowiredprivate TestConfig9 config9;@GetMapping("/test")public void printImportBeanInfo() {System.out.println(config9);System.out.println(config9.testBean());System.out.println(config9.testBean2());}
}
4.2.6.4 测试结果

因为testBean对应的配置存在,所以会成功,testBean2对应的配置在配置文件不存在,所以失败了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/738806.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Visual grounding-视觉定位任务介绍

&#x1f380;个人主页&#xff1a; https://zhangxiaoshu.blog.csdn.net &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️&#xff0c;如有错误敬请指正! &#x1f495;未来很长&#xff0c;值得我们全力奔赴更美好的生活&…

Spring Cloud Alibaba微服务从入门到进阶(一)

Springboot三板斧 1、加依赖 2、写注解 3、写配置 Spring Boot Actuator Spring Boot Actuator 是 Spring Boot 提供的一系列用于监控和管理应用程序的工具和服务。 SpringBoot导航端点 其中localhost:8080/actuator/health是健康检查端点&#xff0c;加上以下配置&#xf…

基于element-plus的Dialog选择控件

翻看之前工程师写的vue2的代码&#xff0c;很多都是复制、粘贴&#xff0c;也真是搞不懂&#xff0c;明明可以写一个控件&#xff0c;不就可以重复使用。很多前端总喜欢element搞一下&#xff0c;ant-design也搞一下&#xff0c;有啥意义&#xff0c;控件也不是自己写的&#x…

Python递归函数你用对了吗?

1.递归函数 递归函数&#xff1a;函数自己调用自己 2.需求 使用函数的方式&#xff0c;计算数字n的阶乘 # 5&#xff01; """ 5! 1 * 2 * 3 * 4 * 5 4! 1 * 2 * 3 * 4 3! 1 * 2 * 3 2! 1 * 2 1! 1综上可以总结出&#xff1a;n! n * (n - 1) "&qu…

什么是防静电晶圆隔离膜?一分钟让你了解抗静电晶圆隔离纸

防静电晶圆隔离膜&#xff0c;也被称为防静电蓄积纸、硅片纸、半导体晶圆盒内缓冲垫片等多种名称&#xff0c;是半导体制造和运输过程中的一种重要辅助材料。 该隔离膜具备多种特性&#xff0c;如防静电、无尘、不掉屑、强韧耐用等&#xff0c;这些特性使其在半导体制造和运输中…

网络安全之从原理看懂XSS

01、XSS的原理和分类 跨站脚本攻击XSS(Cross Site Scripting)&#xff0c;为了不和层叠样式表(Cascading Style Sheets&#xff0c;CSS)的缩写混淆 故将跨站脚本攻击缩写为XSS&#xff0c;恶意攻击者往Web页面里插入恶意Script代码&#xff0c;当用户浏览该页面时&#xff0c…

Word转PDF保持图片原有清晰度

目录 1、需要的软件 2、配置Acrobat PDFMaker 3、配置Acrobat Distiller 4、更改Acrobat PDFMaker中的首选项 5、将word转换成pdf 1、需要的软件 利用Adobe Acrobat DC工具。 打开word&#xff0c;选择Acrobat的插件&#xff0c;选择首选项。 如果没有出现Acrobat插件也…

java并发编程知识点汇总

文章目录 1. Java8新特性1.1 Lambda表达式1.2 函数式接口1.3 Stream流式计算&#xff0c;应用了上述函数式接口能力1.4 接口增强 2. 常用原子类3. 多线程与高并发-juc3.1 谈一谈对volatile的理解3.2 谈一谈对JMM的理解3.3 谈一谈对CAS及底层原理的理解3.4 谈一谈对ABA问题及原子…

【恒源智享云】conda虚拟环境的操作指令

conda虚拟环境的操作指令 由于虚拟环境经常会用到&#xff0c;但是我总忘记&#xff0c;所以写个博客&#xff0c;留作自用。 在恒源智享云上&#xff0c;可以直接在终端界面输入指令&#xff0c;例如&#xff1a; 查看已经存在的虚拟环境列表 conda env list查看当前虚拟…

C语言 编译和链接

1. 翻译环境和运⾏环境 在ANSI?C的任何⼀种实现中&#xff0c;存在两个不同的环境。 第1种是翻译环境&#xff0c;在这个环境中源代码被转换为可执⾏的机器指令。 第2种是执⾏环境&#xff0c;它⽤于实际执⾏代码。 我们来看一下过程&#xff1a; 2. 翻译环境 那翻译环境是…

《幻兽帕鲁》新手入门 幻兽帕鲁新手开荒攻略 幻兽帕鲁配置要求

2024年1月&#xff0c;讨论热度最高的新游无疑是Pocketpair出品的《幻兽帕鲁》。这部作品发售两周即在Steam游戏平台售出超过1200万份&#xff0c;且Xbox/XGP玩家规模超过700万。不仅如此&#xff0c;该游戏同时在线玩家人数超过200万&#xff0c;在Steam的游戏史上仅次于《绝地…

java中几种对象存储(文件存储)中间件的介绍

一、前言 在博主得到系统中使用的对象存储主要有OSS&#xff08;阿里云的对象存储&#xff09; COS&#xff08;腾讯云的对象存储&#xff09;OBS&#xff08;华为云的对象存储&#xff09;还有就是MinIO 这些玩意。其实这种东西大差不差&#xff0c;几乎实现方式都是一样&…

深入理解Java中的ConcurrentSkipListMap:高效并发的有序映射

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 摘要&#xff1a;本文将详细介绍Java中的ConcurrentSkipListMap&#xff0c;一个支持高效并发操作的有序映射。我们将深入探讨其数…

xilinx SDK 2018.3 undefined reference to `f_mount‘,`f_open‘等等

用xilinx SDK 写SD的读写实验时&#xff0c;已经添加了头文件ff.h并且没有报错&#xff0c;但是当用到内部的函数f_mount&#xff0c;f_open’等等时却显示未定义。 很可能是漏掉了在ZYNQ中定义SD的MIO接口&#xff0c;在下方图示中进行定义&#xff08;需要查找自己板子的原理…

Java零基础入门到精通_Day 1

01 Java 语言发展史 Java语言是美国Sun公司(StanfordUniversity Network)在1995年推出的 计算机语言Java之父:詹姆斯高斯林(ames Gosling) 重要的版本过度&#xff1a; 2004年 Java 5.0 2014年 Java 8.0 2018年 9月 Java 11.0 &#xff08;目前所使用的&#xff09; 02 J…

函数的说明文档

函数是纯代码语言&#xff0c;想要理解其含义&#xff0c;就需要一行行去阅读理解代码&#xff0c;效率比较低。 我们可以给函数添加说明文档&#xff0c;辅助理解函数的作用。 语法如下&#xff1a; 通过多行注释的形式&#xff0c;对函数进行说明解释 内容应写在函数体之前…

leetcode 25、k个一组翻转链表

给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值…

SPEL表达式及注入漏洞

SPEL,全称为Spring表达式语言&#xff0c;是一个由 Spring 框架提供的表达式语言。它是一种基于字符串的表达式语言&#xff0c;可以在运行时对对象进行查询和操作。 SpEL 支持在XML和注解配置中使用&#xff0c;它可以在Spring框架的各种组件中使用&#xff0c;如Spring MVC …

springboot261高校专业实习管理系统的设计和开发

基于spring boot的高校专业实习管理系统的设计与实现 摘 要 随着国内市场经济这几十年来的蓬勃发展&#xff0c;突然遇到了从国外传入国内的互联网技术&#xff0c;互联网产业从开始的群众不信任&#xff0c;到现在的离不开&#xff0c;中间经历了很多挫折。本次开发的高校专…

制造行业大数据应用:四大领域驱动产业升级与智慧发展

一、大数据应用&#xff1a;制造行业的智慧引擎 随着大数据技术的不断突破与普及&#xff0c;制造行业正迎来一场前所未有的变革。大数据应用&#xff0c;如同智慧引擎一般&#xff0c;为制造行业注入了新的活力&#xff0c;推动了产业升级与创新发展。 二、大数据应用在制造行…