自定义ConditionalOnXX注解(二)
一、前言
在之前的文章《自定义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,点击查看。
本文作者:烟味i
本文链接:https://www.cnblogs.com/2YSP/p/17080784.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步