SpringBoot - @ConditionalOnProperty アノテーションと @ConditionalOnProperty アノテーションの詳細な説明と使用法

必要

  製品ドッキングのプロセスでは、パブリック サービスが複数の製品を接続します。製品 A はRocketMQ消費に使用され、製品 B は消費する必要がありません。この時点でコードは共有されていますが、製品 B を消費しないようにするにはどうすればよいでしょうか?
  いくつかの方法を検討した後、最初に思い浮かぶのは、RocketMQ監視消費@RocketMQMessageListenerアノテーションを無効にする方法です。しばらく調べてみましたが、アノテーション自体にスイッチがなく、指定されたアノテーションを無効にする適切な方法が見つかりませんでした。別の方向: 条件付きアノテーション。プロテストは効果あり!

@ConditionalOnProperty アノテーション

導入

  1. ではSpringBoot、この注釈を使用して、それが有効になるかどうかを制御できます@Configuration同時に、このアノテーションを使用して、プロパティの属性が設定した設定値に適合しているかどうかを判断することができ、一致する場合はアノテーションによって変更されたクラスまたはメソッドが有効になり、そうでない場合は有効になりません。
  2. このアノテーション@Conditionalは の拡張アノテーションです。

ソースコード分析

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.boot.autoconfigure.condition;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional;

@Retention(RetentionPolicy.RUNTIME)
@Target({
    
    ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({
    
    OnPropertyCondition.class})
public @interface ConditionalOnProperty {
    
    
	//数组,获取property对应的值,与name属性不可以同时使用
    String[] value() default {
    
    };
	//属性名称值的前缀
    String prefix() default "";
	//数组,配置属性值的名称,可与prefix组合使用,不可与value属性同时使用
    String[] name() default {
    
    };
	//比较和name属性值获取到的属性值是否相同,与name组合使用,若true,则加载配置
    String havingValue() default "";
	//缺少配置是否匹配加载,若为true,则表示无该name相关属性值,也加载。反之,不加载。
    boolean matchIfMissing() default false;
}

使用例

新しい Bean クラス

@Data
public class PersonBean {
    
    
    /**
     * name
     */
    private String name;
    /**
     * age
     */
    private int age;
}

テストするアノテーション クラス

/**
 * @Description 测试bean配置
 * @Author LiaoJy
 * @Date 2023/4/17
 */
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "conditional", name = "configuration.switch", havingValue = "true", matchIfMissing = true)
public class BeanConfigTest {
    
    

    @Bean
    public PersonBean personBean() {
    
    
        PersonBean personBean = new PersonBean();
        personBean.setAge(30);
        personBean.setName("andya");
        log.info("========person bean init========");
        return personBean;
    }

}

構成シナリオ 1

conditional:
  configuration:
    switch: false

コンソールログの結果

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.9)

... ...
2023-04-17 14:14:11.620  INFO 25494 --- [           main] c.test.selfcoding.SelfCodingApplication  : No active profile set, falling back to 1 default profile: "default"
2023-04-17 14:14:12.175  INFO 25494 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8001 (http)
2023-04-17 14:14:12.182  INFO 25494 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-04-17 14:14:12.182  INFO 25494 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.64]
2023-04-17 14:14:12.259  INFO 25494 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-04-17 14:14:12.259  INFO 25494 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 609 ms
2023-04-17 14:14:12.445  INFO 25494 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8001 (http) with context path ''
2023-04-17 14:14:12.451  INFO 25494 --- [           main] c.test.selfcoding.SelfCodingApplication  : Started SelfCodingApplication in 1.123 seconds (JVM running for 1.387)

その結果、ログは出力されず========person bean init========、クラスは有効になりません。

構成シナリオ 2

設定しない、または次のように設定します

conditional:
  configuration:
    switch: true

コンソールログの結果

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.9)

... ...
2023-04-17 14:17:35.172  INFO 25577 --- [           main] c.test.selfcoding.SelfCodingApplication  : No active profile set, falling back to 1 default profile: "default"
2023-04-17 14:17:35.771  INFO 25577 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8001 (http)
2023-04-17 14:17:35.777  INFO 25577 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-04-17 14:17:35.777  INFO 25577 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.64]
2023-04-17 14:17:35.859  INFO 25577 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-04-17 14:17:35.859  INFO 25577 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 655 ms
2023-04-17 14:17:35.899  INFO 25577 --- [           main] c.test.selfcoding.config.BeanConfigTest  : ========person bean init========
2023-04-17 14:17:36.134  INFO 25577 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8001 (http) with context path ''
2023-04-17 14:17:36.141  INFO 25577 --- [           main] c.test.selfcoding.SelfCodingApplication  : Started SelfCodingApplication in 1.421 seconds (JVM running for 1.775)

ログが出力され========person bean init========、クラスが有効になっていることがわかります。

@ConditionalOnExpression

導入

  1. 上記の説明はマッチング時の値によって@ConditionalOnPropertyのみ正確に制御でき、それ以上の属性値に応じてマッチングすることはできません(配列値がhavingValueあってもそれによってのみチェックできますvaluehavingValue
  2. @ConditionalOnExpression他の属性値の表現もアノテーションを通じて確認できます。
  3. @ConditionalOnExpression実行式でありSpel、返されるブール値によって条件を満たすかどうかを判断します。

ソースコード

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.boot.autoconfigure.condition;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional;

@Retention(RetentionPolicy.RUNTIME)
@Target({
    
    ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({
    
    OnExpressionCondition.class})
public @interface ConditionalOnExpression {
    
    
	//Spel表达式
    String value() default "true";
}

使用例

テストするアノテーションクラス

/**
 * @Description 测试bean配置
 * @Author LiaoJy
 * @Date 2023/4/17
 */
@Slf4j
@Configuration
//@ConditionalOnProperty(prefix = "conditional", name = "configuration.switch", havingValue = "true", matchIfMissing = true)
@ConditionalOnExpression("!'${conditional.configuration.switch}'.equals('false')")
public class BeanConfigTest {
    
    

    @Bean
    public PersonBean personBean() {
    
    
        PersonBean personBean = new PersonBean();
        personBean.setAge(30);
        personBean.setName("andya");
        log.info("========person bean init========");
        return personBean;
    }

}

このとき、設定が値conditional.configuration.switchでない限り、このクラスが有効になります。false

テストされるアノテーション クラス 2

/**
 * @Description 测试bean配置
 * @Author LiaoJy
 * @Date 2023/4/17
 */
@Slf4j
@Configuration
//@ConditionalOnProperty(prefix = "conditional", name = "configuration.switch", havingValue = "true", matchIfMissing = true)
@ConditionalOnExpression("${conditional.configuration.switch:true}")
public class BeanConfigTest {
    
    

    @Bean
    public PersonBean personBean() {
    
    
        PersonBean personBean = new PersonBean();
        personBean.setAge(30);
        personBean.setName("andya");
        log.info("========person bean init========");
        return personBean;
    }

}

現時点では、値conditional.configuration.switchとして設定されている場合のみfalse、このクラスは有効になりません。

その他の使用例

  1. ブール属性
@ConditionalOnExpression("${
    
    conditional.configuration.switch:true}
  1. 複数のブール型プロパティ (いずれか 1 つが満たされている場合)
@ConditionalOnExpression("${conditional.configuration.switch1:true} || ${conditional.configuration.switch2:true}")
  1. 設定値が数値に等しい
@ConditionalOnExpression("${conditional.configuration.switch} == 1")
@ConditionalOnExpression("${conditional.configuration.switch} != 1")
  1. 設定値は指定された文字列と同じです
@ConditionalOnExpression("'${conditional.configuration.switch}'.equals('yes')")
  1. 複数の設定値が同じである
@ConditionalOnExpression("'${conditional.configuration.str1}'.equals('${conditional.configuration.str2}')")
  1. … …

要約する

  最初はただ使ってみたかったのですが、使っているうちにさらに爽快感@ConditionalOnPropertyが増します!@ConditionalOnExpression

おすすめ

転載: blog.csdn.net/Andya_net/article/details/130196150