一、前言

在之前的文章《自定义ConditionalOnXX注解》中,介绍了Conditional注解的实现原理和实现自定义Conditional注解的基础方法,但是有些场景我们需要用一个ConditionalOnXX注解来实现多条件的与(AND)或(OR)非(NOT)逻辑,本文就是介绍这种复杂场景的应用。

二、自定义注解合并多条件

假设有一个bean MyBean,我们想通过当前操作系统标识来控制其是否注入到Spring容器中。

首先创建windows和mac系统的condition

OnWindowsCondition

/**
* @author Ship
* @version 1.0.0
* @description:
* @date 2023/01/31 10:20
*/
public class OnWindowsCondition implements Condition { @Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return SystemUtils.IS_OS_WINDOWS;
}
}

OnMacCondition

/**
* @author Ship
* @version 1.0.0
* @description:
* @date 2023/01/31 10:20
*/
public class OnMacCondition implements Condition { @Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return SystemUtils.IS_OS_MAC;
}
}

2.1 与(AND)合并条件

SpringBoot提供了一个抽象类AllNestedConditions,具体用法其类注释写的比较清楚了如下:

/**
* {@link Condition} that will match when all nested class conditions match. Can be used
* to create composite conditions, for example:
*
* <pre class="code">
* static class OnJndiAndProperty extends AllNestedConditions {
*
* OnJndiAndProperty() {
* super(ConfigurationPhase.PARSE_CONFIGURATION);
* }
*
* @ConditionalOnJndi()
* static class OnJndi {
* }
*
* @ConditionalOnProperty("something")
* static class OnProperty {
* }
*
* }
* </pre>
* <p>
* The
* {@link org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase
* ConfigurationPhase} should be specified according to the conditions that are defined.
* In the example above, all conditions are static and can be evaluated early so
* {@code PARSE_CONFIGURATION} is a right fit.
*
* @author Phillip Webb
* @since 1.3.0
*/
public abstract class AllNestedConditions extends AbstractNestedCondition { }

只需要新建一个condition类继承AllNestedConditions,重写构造方法并添加条件即可,需要注意的是构造方法里的ConfigurationPhase枚举分为两种情况,具体用哪个取决于Condition注解的使用场景。

ConfigurationPhase.PARSE_CONFIGURATION: 用于控制配置类是否生效

ConfigurationPhase.REGISTER_BEAN: 用于控制Bean是否加载

创建条件类OnWindowsAndMacCondition

package cn.sp.condition.nested;

import cn.sp.condition.OnMacCondition;
import cn.sp.condition.OnWindowsCondition;
import org.springframework.boot.autoconfigure.condition.AllNestedConditions;
import org.springframework.context.annotation.Conditional; /**
* @author Ship
* @version 1.0.0
* @description: 只有当所有条件都满足时,bean才会被加载
* @date 2023/01/31 10:27
*/
public class OnWindowsAndMacCondition extends AllNestedConditions { public OnWindowsAndMacCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
} @Conditional(OnWindowsCondition.class)
static class OnWindows{ } @Conditional(OnMacCondition.class)
static class OnMac{ }
}

自定义注解@ConditionalOnWindowsAndMac

/**
* @author Ship
* @version 1.0.0
* @description: 条件之是windows且mac系统
* @date 2023/01/31 10:19
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(value = OnWindowsAndMacCondition.class)
public @interface ConditionalOnWindowsAndMac { }

2.2 或(OR)合并条件

创建条件类OnWindowsOrMacCondition

/**
* @author Ship
* @version 1.0.0
* @description: 只要有一个条件满足时,bean就会被加载
* @date 2023/01/31 10:27
*/
public class OnWindowsOrMacCondition extends AnyNestedCondition { public OnWindowsOrMacCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
} @Conditional(OnWindowsCondition.class)
static class OnWindows{ } @Conditional(OnMacCondition.class)
static class OnMac{ }
}

自定义注解@ConditionalOnWindowsOrMac

/**
* @author Ship
* @version 1.0.0
* @description: 条件之是windows或mac系统
* @date 2023/01/31 10:19
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(value = OnWindowsOrMacCondition.class)
public @interface ConditionalOnWindowsOrMac { }

2.3 非(NOT)合并条件

创建条件类OnNotWindowsCondition

/**
* @author Ship
* @version 1.0.0
* @description: 只有当所有条件都不满足时,bean才会被加载
* @date 2023/01/31 10:27
*/
public class OnNotWindowsCondition extends NoneNestedConditions { public OnNotWindowsCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
} @Conditional(OnWindowsCondition.class)
static class OnWindows { }
}

自定义注解@ConditionalOnNotWindows

/**
* @author Ship
* @version 1.0.0
* @description: 条件之不是windows系统
* @date 2023/01/31 10:19
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(value = OnNotWindowsCondition.class)
public @interface ConditionalOnNotWindows { }

三、测试验证

TestConfiguration配置类添加了MyBean的注入方法

@Configuration
public class TestConfiguration { @ConditionalOnWindowsAndMac
// @ConditionalOnWindowsOrMac
// @ConditionalOnNotWindows
@Bean
public MyBean myBean() {
System.out.println("Initialized bean:myBean...");
return new MyBean();
}
}

@ConditionalOnWindowsAndMac测试

本人机器是Mac系统,启动项目控制台没有任何输出,表明结果正常,毕竟没有既是windows又是mac的系统。

@ConditionalOnWindowsOrMac测试

将myBean()方法打上@ConditionalOnWindowsOrMac注解,启动项目控制台输出如下:

2023-01-31 20:51:25.584  INFO 16669 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 967 ms
Initialized bean:myBean...
2023-01-31 20:51:25.955 INFO 16669 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path ''
2023-01-31 20:51:25.965 INFO 16669 --- [ main] cn.sp.SpringExtensionApplication : Started SpringExtensionApplication in 2.118 seconds (JVM running for 3.965)

说明MyBean被加载了,条件生效。

@ConditionalOnNotWindows测试

将myBean()方法打上@ConditionalOnNotWindows注解,启动项目控制台也打印出了[Initialized bean:myBean...],说明MyBean被加载了,条件生效。

文章代码已上传至github,点击查看

自定义ConditionalOnXX注解(二)的更多相关文章

  1. 自定义ConditionalOnXX注解

    一.Conditional注解介绍 对SpringBoot有足够了解的小伙伴应该都用过Conditional系列注解,该注解可用在类或者方法上用于控制Bean的初始化. 常用的Conditional注 ...

  2. asp.net mvc3 数据验证(三)—自定义数据注解

    原文:asp.net mvc3 数据验证(三)-自定义数据注解         前两节讲的都是asp.net mvc3预先设定的数据注解,但是系统自由的数据注解肯定不适合所有的场合,所以有时候我们需要 ...

  3. spring-cloud: eureka之:ribbon负载均衡自定义配置(二)

    spring-cloud: eureka之:ribbon负载均衡自定义配置(二) 有默认配置的话基本上就是轮询接口,现在我们改用自定义配置,同时支持:轮询,随机接口读取 准备工作: 1.eureka服 ...

  4. SpringBoot自定义Condition注解

        最近碰到个这样的需求,需要同一套代码适配个版本数据库(数据库不同,且部分表的字段及关联关系可能会不同),即这套代码配置不同的数据库都能跑.项目采用的框架为SpringBoot+Mybatis. ...

  5. 【Spring Cloud】Spring Cloud之自定义@SpringCloudProfile注解实现@Profile注解的功能

    一.为什么会想到定义@SpringCloudProfile这样的注解 首页提一下@Profile注解:它主要用与Spring Boot多环境配置中,指定某个类只在指定环境中生效,比如swagger的配 ...

  6. springcloud项目实现自定义权限注解进行接口权限验证

    一般在项目开发中会根据登录人员的权限大小对接口也会设置权限,那么对接口权限是怎么实现的呢,大多数都是用自定义权限注解,只需要在接口上加上一个注解就可以实现对接口的权限拦截,是否对该接口有权调用 接下来 ...

  7. 自定义校验注解ConstraintValidator

    一 前言 系统执行业务逻辑之前,会对输入数据进行校验,检测数据是否有效合法的.所以我们可能会写大量的if else等判断逻辑,特别是在不同方法出现相同的数据时,校验的逻辑代码会反复出现,导致代码冗余, ...

  8. [译]SpringMVC自定义验证注解(SpringMVC custom validation annotations)

    在基于SpringMVC框架的开发中,我们经常要对用户提交的字段进行合法性验证,比如整数类型的字段有个范围约束,我们会用@Range(min=1, max=4).在实际应用开发中,我们经常碰到一些自己 ...

  9. 自定义view(二)

    这里是自定义view(二),上一篇关于自定义view的一些基本知识,比如说自定义view的步骤.会涉及到哪些函数以及如何实现自定义属性,同时实现了一个很基础的自定义控件,一个自定义的计时器,需要看的人 ...

  10. jsr-303 参数校验—自定义校验注解

    1.为什么要自定义? 通过上篇学习,了解到很多常用注解了,但是呢,总是有那么些需求....   2.案例分析(手机号格式) 2.1.需要验证的实体 Bean public class LoginVo ...

随机推荐

  1. 微服务用yml安装系统(第一版)

    当用微服务安装系统后,面临服务较多,一个一个安装比较麻烦,是否有统一的脚本可以直接执行安装呢?答案是肯定的: 1.首先介绍一下所有安装脚本,如下图 spd-volume:是各服务外挂的资料卷 comm ...

  2. 我手写了一个RPC框架。成功帮助读者斩获字节、阿里等大厂offer。

    本着开源精神,本项目README已经同步了英文版本.另外,项目的源代码的注释大部分也修改为了英文. 如访问速度不佳,可放在 Gitee 地址:https://gitee.com/SnailClimb/ ...

  3. 21.12 Python 实现网站服务器

    Web服务器本质上是一个提供Web服务的应用程序,运行在服务器上,用于处理HTTP请求和响应.它接收来自客户端(通常是浏览器)的HTTP请求,根据请求的URL.参数等信息生成HTTP响应,并将响应返回 ...

  4. 4.8 C++ Boost 应用JSON解析库

    property_tree 是 Boost 库中的一个头文件库,用于处理和解析基于 XML.Json 或者 INFO 格式的数据. property_tree 可以提供一个轻量级的.灵活的.基于二叉数 ...

  5. Python 多线程爬取西刺代理

    西刺代理是一个国内IP代理,由于代理倒闭了,所以我就把原来的代码放出来供大家学习吧. 首先找到所有的tr标签,与class="odd"的标签,然后提取出来. 然后再依次找到tr标签 ...

  6. Cheat Engine 官方教程汉化

    CE修改器官方教程汉化版,区别于前款教程,官方教程中使用的是Tutorial64位程序,如下是经过翻译后的官方文档. 第一步:欢迎 当教程启动时,您应该会看到类似的东西,您只需在阅读帮助文本后单击&q ...

  7. 使用 docker 部署 kafka

    在很多时候我们需要使用到消息队列, 其中 kafka 是一个非常优秀的消息队列, 在我们平时开发中也经常会用到, 但是在开发环境中部署 kafka 是一个非常麻烦的事情 在 kafka 官网上, 有一 ...

  8. 6、后端学习规划:Java学习 - 学习规划系列文章

    Java语言在现在的编程语言排行榜上也是前5的存在.经过这么些年的发展,Java的发展没有C#这么大,但是在编程领域,因为有MVC架构,以及Spring框架的支持,以及微服务架构等等,Java这些年也 ...

  9. 离线解锁 CodeCombat 全关卡教程 使用docker安装实现

    前期准备 下载安装docker desktop https://www.123pan.com/s/fmvUVv-HqApH, 这个安装不会的随便搜一个教程,挺多的.我随便找了一个知乎的 Windows ...

  10. Mygin之错误恢复Recover中间件

    本篇是mygin这个系列的最后一篇.如果想自己动手实现一个类似Gin的Web框架,建议从 mgin第一篇开始, 总代码行数有效行数只有600多行 github源码 mygin 目的 实现错误处理机制 ...