自定义ConditionalOnXX注解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义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);
 *    
 *
 *    &#064;ConditionalOnJndi()
 *    static class OnJndi 
 *    
 *
 *    &#064;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注解的主要内容,如果未能解决你的问题,请参考以下文章

自定义注解实现解密+单个属性解密

springboot中关于自定义注解校验

如何在java web项目中添加自定义注解

java里的自定义注解类型 有啥用?

Java 注解自定义注解 ( 使用注解实现简单测试框架 )

在Spring中怎么拦截自定义的注解