一、前言

在之前的文章《自定义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. kubernetes中不可见的OOM

    最近看了一篇文章:Tracking Down "Invisible" OOM Kills in Kubernetes,其讲述的是由于内存不足导致Pod中的进程被killed,但Po ...

  2. 学习React中的jsx-保证你看的明明白白

    安装react的脚手架 1==>行 npx create-react-app myreactdemo01 解释一下: npx create-react-app 你的项目名称 npx create ...

  3. 【解决了一个小问题】alert manager要怎么样才能触发告警到企业微信上?

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 07-15:花了几个小时仍然是没走通这个流程,把中间结果记 ...

  4. 【学到了】golang的[]byte可以append string类型的数据

    上代码: func Test_use_string(t *testing.T){ arr := make([]byte,0, 100) arr = append(arr, "abcd&quo ...

  5. python安装与python、pip的环境变量配置

    进入官网 在你常用的搜索引擎中输入 python官网 然后进入. 可直接点击本链接 python官网进入: 也可在浏览器地址栏输入www.python.org回车进入官网. 下载 将鼠标放到菜单栏中的 ...

  6. 【6】opencv采用映射技术实现鱼眼镜头校正和鱼眼镜头还原全景图。

    相关文章: [1]windows下安装OpenCV(4.3)+VS2017安装+opencv_contrib4.3.0配置 [2]Visual Studio 2017同时配置OpenCV2.4 以及O ...

  7. C/C++ 实现Socket交互式服务端

    在 Windows 操作系统中,原生提供了强大的网络编程支持,允许开发者使用 Socket API 进行网络通信,通过 Socket API,开发者可以创建.连接.发送和接收数据,实现网络通信.本文将 ...

  8. 2.1 PE结构:文件映射进内存

    PE结构是Windows系统下最常用的可执行文件格式,理解PE文件格式不仅可以理解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,在任何一款操作系统中,可执行程序在被装入内存之 ...

  9. MongoDB 7.0 搭建 Sharding 副本集群

    本文是在ubuntu 22.03 系统版本上部署的,最低支持mongodb-6.0.4以上,所以这里安装mongodb7.0 1 安装mongo 安装方式有多种,本人是使用的第一种方式,时间也就20分 ...

  10. ABC311_g One More Grid Task 题解

    题目链接:Atcoder 或者 洛谷 对于解决二维区间内的最值类型问题,我们常常有一类特别好用的方法,就是悬线法,它可以看做是单调栈的子集,但更加好理解和书写. 对于悬线法,我们有一个常见的模型,找出 ...