自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

強大!基于Spring Boot自定義條件動態(tài)注冊組件

開發(fā) 開發(fā)工具
當(dāng)Spring Boot預(yù)設(shè)的條件注解不能滿足我們的需求時,我們還可以通過自定義的方式來實現(xiàn)更為復(fù)雜和特定的條件邏輯。 接下來,我們將詳細介紹有關(guān)自定義條件注解的多方面知識的應(yīng)用。

環(huán)境:SpringBoot3.4.0

1. 簡介

@Conditional是Spring 4.0版本引入的一個強大注解,它允許開發(fā)者根據(jù)特定條件來決定是否創(chuàng)建某個Bean。該注解只有當(dāng)滿足預(yù)設(shè)條件時,Spring容器才會將對應(yīng)的Bean實例化并加入到應(yīng)用程序的上下文中。

通過@Conditional注解,開發(fā)者可以根據(jù)不同的環(huán)境(如開發(fā)、測試、生產(chǎn)環(huán)境)、配置文件中的屬性、類路徑中的特定類是否存在,或者任何自定義的邏輯條件,來動態(tài)地控制Bean的創(chuàng)建過程。這種機制極大地提高了Spring應(yīng)用程序的可配置性和靈活性,使得開發(fā)者能夠根據(jù)不同的場景和需求,智能地選擇性地裝配Bean。

@Conditional注解通常與@Configuration和@Bean注解一起使用,以標(biāo)記那些需要條件化創(chuàng)建的Bean。在Spring Boot中,@Conditional注解更是被廣泛應(yīng)用,衍生出了如@ConditionalOnProperty、@ConditionalOnBean、@ConditionalOnClass等多個便捷的條件注解,進一步簡化了條件配置的過程。

當(dāng)Spring Boot預(yù)設(shè)的條件注解不能滿足我們的需求時,我們還可以通過自定義的方式來實現(xiàn)更為復(fù)雜和特定的條件邏輯。

接下來,我們將詳細介紹有關(guān)自定義條件注解的多方面知識的應(yīng)用。

圖片圖片

2. 實戰(zhàn)案例

2.1 自定義Condition接口

這里我們簡單的根據(jù)配置文件中的屬性來決定是否注冊Bean對象。

public class EnvCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Environment env = context.getEnvironment();
    return "true".equals(env.getProperty("pack.api.enabled"));
  }
}

只有配置文件中的"pack.api.enabled"設(shè)置為true才會對相應(yīng)的Bean進行注冊;自定義注解:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(ApiCondition.class)
public @interface ConditionalOnApi {
}

接下來,進行測試:

@RestController
@RequestMapping("/api")
@ConditionalOnApi
public class ApiController {


  @PostConstruct
  public void init() {
    System.err.println("ApiController init...") ;
  }
}

首先,配置文件不對pack.api.enabled進行配置,如果啟動容器后沒有輸出任何內(nèi)容則表示我們的條件注解生效了。

圖片圖片

沒有任何的輸出:

配置文件中設(shè)置pack.api.enabled=true, 再次啟動服務(wù)

圖片

成功注冊bean。

2.2 帶參數(shù)增強實現(xiàn)

在上面的示例中,我們直接在代碼中硬編碼了要判斷的屬性,這種做法缺乏靈活性。因此,在該示例中,我們將采用自定義注解屬性來實現(xiàn)條件判斷,以增強代碼的靈活性和可配置性。

修改注解如下:

public @interface ConditionalOnApi {
  
  String value() ;
}

修改條件類:

public class ApiCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Map<String, Object> attrs = metadata.getAnnotationAttributes(
        ConditionalOnApi.class.getName()) ;
    String key = (String) attrs.get("value") ;
    Environment env = context.getEnvironment() ;
    return "true".equals(env.getProperty(key)) ;
  }
}

最后,修改使用處。

@ConditionalOnApi("pack.api.enabled")
public class ApiController {}

通過上面的改造我們的自定義條件靈活多了。

2.3 基于SpringBootCondition實現(xiàn)

通過繼承SpringBootCondition實現(xiàn)條件是官方推薦的方式。它的強大之處在于它提供了有用的日志記錄功能,以幫助用戶診斷哪些類被加載了。

自定義條件:

public class ApiMonitorCondition extends SpringBootCondition {
  private static final ConditionMessage.Builder message = ConditionMessage.forCondition("API Monitor");


  @Override
  public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
    String monitorEnabled = context.getEnvironment().getProperty("pack.api.monitor.enabled");
    if ("true".equals(monitorEnabled)) {
      return ConditionOutcome.match(message.available("開啟API監(jiān)控功能"));
    }
    return ConditionOutcome.noMatch(message.because("API監(jiān)控功能關(guān)閉"));
  }
}

自定義注解:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(ApiMonitorCondition.class)
public @interface ConditionalOnApiMonitor {
}

使用條件注解:

@Configuration
@ConditionalOnApiMonitor
public class ApiMonitorConfig {
}

接下來,進行測試。

首先,不配置pack.api.monitor.enabled或者設(shè)置為false,同時將debug設(shè)置為true,啟動服務(wù)控制臺輸出如下:

圖片圖片

最后,將pack.api.monitor.enabled設(shè)置為true,控制臺輸出如下:

圖片圖片

2.4 多條件組合實現(xiàn)

在該案例中我們將采用多個條件來進行判斷是否符合條件。我們還是使用上面的示例,條件的判斷我們不僅判斷屬性,而且還會判斷相應(yīng)的類及Bean是否存在。

這里我們直接修改上面的條件注解:

public class ApiMonitorCondition extends SpringBootCondition {
  private static final ConditionMessage.Builder message = ConditionMessage.forCondition("API Monitor");
  private static final String CLASS_NAME = "com.pack.condition.test.MonitorComponent" ;


  @Override
  public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
    String monitorEnabled = context.getEnvironment().getProperty("pack.api.monitor.enabled");
    boolean enabled = "true".equals(monitorEnabled) ;
    // 判斷對應(yīng)的類是否存在
    boolean isPresent = isPresent(CLASS_NAME, context.getClassLoader()) ;
    if (enabled) {
      if (isPresent) {
        try {
          // 判斷對應(yīng)的bean是否存在
          ConfigurableListableBeanFactory beanFactory = context.getBeanFactory() ;
          if (beanFactory.containsBean("monitorComponent")) { 
            return ConditionOutcome.match(message.available("開啟API監(jiān)控功能"));
          }
          return ConditionOutcome.noMatch(message.because("容器不存在beanName=monitorComponent的Bean對象"));
        } catch (Exception e) {
          return ConditionOutcome.noMatch(message.because("容器不存在【" + CLASS_NAME + "】類型的Bean"));
        }
      } else {
        return ConditionOutcome.match(message.because("API監(jiān)控未能開啟缺少【" + CLASS_NAME + "】類"));
      }
    } else {
      return ConditionOutcome.noMatch(message.because("API監(jiān)控功能關(guān)閉"));
    }
  }
  
  private static boolean isPresent(String className, ClassLoader classLoader) {
    try {
      resolve(className, classLoader);
      return true;
    }
    return false ;
  }
  private static Class<?> resolve(String className, ClassLoader classLoader) throws ClassNotFoundException {
    if (classLoader != null) {
      return Class.forName(className, false, classLoader);
    }
    return Class.forName(className);
  }
}

以上我們就完成了多個條件組件判斷。

測試結(jié)果:

圖片圖片

存在對應(yīng)的類及bean時輸出如下:

圖片圖片

最終是匹配的。

責(zé)任編輯:武曉燕 來源: Spring全家桶實戰(zhàn)案例源碼
相關(guān)推薦

2024-10-14 17:18:27

2022-04-24 15:17:56

鴻蒙操作系統(tǒng)

2022-06-27 08:16:34

JSON格式序列化

2009-06-24 15:13:36

自定義JSF組件

2023-02-20 15:20:43

啟動頁組件鴻蒙

2021-11-01 10:21:36

鴻蒙HarmonyOS應(yīng)用

2021-07-13 14:05:37

單點登錄頁面

2022-09-16 15:34:32

CanvasArkUI

2022-07-06 20:24:08

ArkUI計時組件

2022-10-25 15:12:24

自定義組件鴻蒙

2022-10-26 15:54:46

canvas組件鴻蒙

2009-06-25 14:53:35

自定義UI組件JSF框架

2022-12-07 08:56:27

SpringMVC核心組件

2022-03-01 16:09:06

OpenHarmon鴻蒙單選組件

2021-09-15 10:19:15

鴻蒙HarmonyOS應(yīng)用

2022-06-30 14:02:07

鴻蒙開發(fā)消息彈窗組件

2023-01-03 07:40:27

自定義滑塊組件

2022-07-15 16:45:35

slider滑塊組件鴻蒙

2018-06-21 14:46:03

Spring Boot異步調(diào)用

2022-06-20 15:43:45

switch開關(guān)鴻蒙
點贊
收藏

51CTO技術(shù)棧公眾號