写在前面

当我们构建一个 Spring 应用的时候,有时我们想在满足指定条件的时候才将某个 bean 加载到应用上下文中, 在Spring 4.0 时代,我们可以通过 @Conditional 注解来实现这类操作

我们看到 @Conditional 注解接收的参数是 extends Condition 接口的泛型类,也就是说,我们要使用 @Conditional 注解,只需要实现 Condition 接口并重写其方法即可:

看到接口的 matches 方法返回的是 boolean 类型,是不是和我们自定义 validation annotation 有些类似,都是用来判断是否满足指定条件。另外注意看,以上注解和接口都在 org.springframework.context.annotation package 中

终于到了 Spring Boot 时代,在这个全新的时代,Spring Boot 在 @Conditional 注解的基础上进行了细化,无需出示复杂的介绍信 (实现 Condition 接口),只需要手持预定义好的 @ConditionalOnXxxx 注解印章的门票,如果验证通过,就会走进 Application Context 大厅

注解详解

Spring Boot 对 @Conditional 注解为我们做了细化,这些注解都定义在 org.springframework.boot.autoconfigure.condition package 下

逐个打开这 13 个注解,我们发现这些注解上有相同的元注解:

从这些标记上我们可以了解如下内容:

  • 都可以应用在 TYPE 上,也就是说,Spring 自动扫描的一切类 (@Configuration, @Component, @Service, @Repository, or @Controller) 都可以通过添加相应的 @ConditionalOnXxxx 来判断是否加载
  • 都可以应用在 METHOD 上,所以有 @Bean 标记的方法也可以应用这些注解
  • 都是用了 @Conditional 注解来标记,OnBeanCondition 等自定义 Condition 还是实现了 Condition 接口的,换汤不换药,没什么神秘的,只不过做了更具象的封装罢了,来看类依赖图:

其实看这些注解字面意思已经能理解这些注解的含义,但是我们还是要说明具体的使用以及一些注意事项,我按照个人使用频次由高到低讲解:

@ConditionalOnProperty

毫无疑问这个注解是榜首

这个条件解释是: application.properties 或 application.yml 文件中 mybean.enable 为 true 才会加载 MyCondition 这个 Bean,如果没有匹配上也会加载,因为 matchIfMissing = true,默认值是 false。

@ConditionalOnBean 和 ConditionalOnMissingBean

有时候我们需要某个 Bean 已经存在应用上下文时才会加载,那么我们会用到 @ConditionalOnBean 注解:

与之相反,有时候我们需要某个 Bean 不存在于应用上下文时才会加载,那么我们会用到 @ConditionalOnMissingBean 注解

@ConditionalOnClass 和 @ConditionalOnMissingClass

不要嫌我废话,和上面的一样,只不过判断某个类是否存在于 classpath 中,这就不做过多说明了

@ConditionalOnExpression

如果我们有更复杂的多个配置属性一起判断,那么我们就可以用这个表达式了:

只有当两个属性都为 true 的时候才加载 MyModule,到这里要顺便揭晓上一篇文章灵魂追问 3,其中 :true 就是: 如果没有为该属性设置值,则为该属性设置默认值true, 其实这就是@Vaue 注解的规范,一切 SpEL 都可以应用在这里.

写到这,我常用的已经用完了,还要硬着头皮介绍其他几个内容 ,开个玩笑,咱们继续:

@ConditionalOnSingleCandidate

这个注解和 @ConditionalOnBean 类似,为了更好的说明该注解的使用 (其实是 才疏学浅 ) ,我只能翻译一下类的注释了

只有指定类已存在于 BeanFactory 中,并且可以确定单个候选项才会匹配成功

BeanFactory 存在多个 bean 实例,但是有一个 primary 候选项被指定(通常在类上使用 @Primary 注解),也会匹配成功。实质上,如果自动连接具有定义类型的 bean 匹配就会成功

目前,条件只是匹配已经被应用上下文处理的 bean 定义,本身来讲,强烈建议仅仅在 auto-configuration 类中使用这个条件,如果候选 bean 被另外一个 auto-configuration 创建,确保使用该条件的要在其后面运行

@ConditionalOnResource

如果我们要加载的 bean 依赖指定资源是否存在于 classpath 中,那么我们就可以使用这个注解

看到这个 logback.xml 是不是很亲切,在我们引入第三方工具类都可以添加类似的开关

接下来的是真冷门,大家有个印象,如果有需要,至少能想到用这些注解实现灵活配置就好了

@ConditionalOnJndi

只有指定的资源通过 JNDI 加载后才加载 bean

@ConditionalOnJava

只有运行指定版本的 Java 才会加载 Bean

@ConditionalOnWebApplication 和 @ConditionalOnNotWebApplication

只有运行在 web 应用里才会加载这个 bean

与之相反,在非 web 环境才加载 bean

@ConditionalOnCloudPlatform

这个注解冷的我呼吸都要停止了,只有运行在指定的云平台上才加载指定的 bean,CloudPlatform 是 org.springframework.boot.cloud 下一个 enum 类型的类,大家可以打开自行看看:

到此,Spring Boot 为我们提供的这 13 个注解就介绍完了,但是没有结束,下面的一些冷门知识,你需要知道:

组合条件

组合条件 AND

如果我们想多个条件一起应用,并且条件的关系是 and,我们只需要在类上使用多个@ConditionalOnXxxx 就可以了 (你这也叫冷门?) ,当然也可以继承 AllNestedConditions类封装我们多个条件

这样就有了组合 and 条件,只有内部所有条件都满足,才加载指定 bean

组合条件 OR

如果我们希望组合的条件是 or 的关系,我们该怎么办呢? 我们可以通过继承 AnyNestedCondition 来完成这一要求,示例代码和上面一样,大家自行打开 AnyNestedCondition 类,查看类说明即可

条件组合 NONE

有 and 和 or 就肯定有 non(非),我们可以通过继承 NoneNestedConditions 完成这一要求,大家自行查看即可

自定义注解

通过组合方式实现了多条件逻辑应用,我们需要应用这些组合条件也就要自定义注解,其实文章开头已经讲过了,模仿内置的 13 个注解写就好了:

只需要通过@Conditional注解指定我们自定义的 condition 类就好了,然后应用到你想用的地方就好了

还是推荐大家看 RabbitMq 的 RabbitAutoConfiguration 类,这个类里面主流的注解都是用了 (只看这一个类就好了),大家看框架理解学习这些注解是更好的方式:

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfiguration.java

总结

到这里,你已经了解了如何灵活配置 bean,结合之前的文章,相信的定义会更加灵活,希望大家打开 IDE,自行查看这些注解,了解更多具体内容

灵魂追问

  1. SpringBoot 添加了 web starter,有哪些方法将其更改为非 web 应用?
  2. Java8 Stream 也有 findAny,findAll 这类的操作,这都是匹配,你有使用过吗?
  3. 看下面这段代码,如果 classpath 中没有 MyBean class,编译会报错,那这个注解什么用呢?
@Configuration @ConditionalOnClass(MyBean.class)public class MyConfiguration{ // omitted }

bean ref的bean可以做判断吗_Spring Boot @Condition 注解,组合条件你知道吗相关推荐

  1. Spring 管理Bean(获取Bean,初始化bean事件,自动匹配ByName······等)

    1.实例化spring容器 和 从容器获取Bean对象 实例化Spring容器常用的两种方式: 方法一: 在类路径下寻找配置文件来实例化容器 [推荐使用] ApplicationContext ctx ...

  2. 标签系列二:spring 中bean解释以及bean标签里面的属性

    一.bean标签: 英文解释:Defines a single (usually named) bean. A bean definition may contain nested tags for ...

  3. Spring Bean、XML方式Bean配置、Bean实例化配置、Bean注入

    文章目录 Bean管理 一.SpringBoot Bean 初了解 1.1 了解 1.2 Bean的作用域 1.2.1 注意事项 1.3 第三方Bean 二. 基于XML方式Bean的配置 2.1 S ...

  4. Spring中初始化bean和销毁bean的时候执行某个方法的详解

    关于在spring  容器初始化 bean 和销毁前所做的操作定义方式有三种: 第一种:通过注解@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作 ...

  5. Spring Core之 Customizing the Nature of a Bean(自定义bean的相关性质)

    文章目录 一.Lifecycle Callbacks (生命周期回调函数) 1.Initialization Callbacks(初始化回调) 2.Destruction Callbacks(销毁回调 ...

  6. EJB学习(四)——Enterprise Bean(企业Bean)和Entity Bean(实体Bean)

        一.为什么使用EJB ? 企业Bean执行在EJB容器中.企业Bean实际上就是一个封装了业务逻辑的Java类,那么我们为什么要使用EJB呢 ? 1.最重要的原因:分布式.简要的说,分布式能够 ...

  7. 当singleton Bean依赖propotype Bean,可以使用在配置Bean添加look-method来解决

    在Spring里面,当一个singleton bean依赖一个prototype bean,因为singleton bean是单例的,因此prototype bean在singleton bean里面 ...

  8. 学好spring系列之Wiring Bean(装配Bean)

    在上两篇的博文中,分别对spring框架中的两个很重要的概念DI(Dependency Injection)和AOP(Aspect-Oriented programming)做了介绍,或许不那么完美, ...

  9. Spring定义Bean的两种方式:<bean>和@Bean

    前言: Spring中最重要的概念IOC和AOP,实际围绕的就是Bean的生成与使用. 什么叫做Bean呢?我们可以理解成对象,每一个你想交给Spring去托管的对象都可以称之为Bean. 今天通过S ...

最新文章

  1. android8.1新功能,Android 8.1新特性:烦人的“正在后台运行”,拜拜
  2. go TypeError: Failed to execute ‘fetch‘ on ‘Window‘: Request with GET/HEAD method cannot have body.
  3. mysql replication health is not ok_mysql配置mha高可用防火墙未关闭报错
  4. Qt4.8编译MYSQL驱动
  5. Wireshark零基础使用教程(超详细)
  6. web.xml之context-param与init-param的区别与作用【转】
  7. [UOJ22]外星人
  8. 洛谷 P2525 Uim的情人节礼物·其之壱
  9. 物联网产业链全景图(附另13大电子行业全景图,必收藏)
  10. HTML中怎么点击超链接让新页面在另一个窗口打开?
  11. android edittext 英文数字键盘,Adroid EditText限制输入数字与英文默认弹出数字键盘...
  12. [Python] 微信for PC自动群发消息、图片以及文件
  13. 程序员如何实现财务自由?
  14. 消息队列——RabbitMQ消息队列集群
  15. HDU 2188-悼念512汶川大地震遇难同胞——选拔志愿者
  16. Beta测试应用程序完整指南
  17. 全面掌控!打造智慧城市建设的“领导驾驶舱”
  18. linux can总线接收数据串口打包上传_使用Zedboard开发板学习Linux的移植及驱动开发...
  19. Excel-常用宏技巧(5)
  20. TL437x-IDK基于AM437x的FPGA与ARM通信测试

热门文章

  1. pandas pivot_table透视表、crosstab交叉表、aggfunc函数详解及实战
  2. linux怎么安装java环境变量_如何简单的在linux上安装jdk并配置环境变量
  3. 纳米孔测序高错误区域恢复率高达99%,肖传乐/刘奕志/王建新等在Nature子刊发表新校正组装算法
  4. 用php计算自由落体,js模仿物理中的自由落体现象
  5. fiash星空动画制作_三维动画制作的详细流程
  6. python 离线下载和安装第三方库 .whl wheel 文件
  7. flask restful 模板
  8. 灾难恢复级别_如何实施云计算灾难恢复
  9. mfc 访问局域网mysql_数据库操作:MFC连接与MYSQL
  10. matlab方波假频现象分析,基于MATLAB 的信号时域采样及频率混叠现象分析