Spring 中的 @ConditionalOnProperty 註解

1、概述

介紹@ConditionalOnProperty註解的主要目的。

2、@ConditionalOnProperty的目的

通常,在開發基於Spring的應用程序時,可能需要根據配置屬性的存在和值有條件地創建一些bean。

例如,取決於是否將屬性值設置爲“ prod”或“ test”,可能想要註冊一個DataSource bean來指向生產或測試數據庫。

幸運的是,實現這一目標並不像想象的那樣困難。 Spring框架正是爲此目的提供了@ConditionalOnProperty註解。

簡而言之,@ConditionalOnProperty僅在存在環境屬性且具有特定值的情況下才啓用Bean註冊。 默認情況下,必須定義指定的屬性,並且不等於false。

現在已經熟悉了@ConditionalOnProperty註解的用途,接下來深入地瞭解它的工作原理。

3、實踐中的@ConditionalOnProperty註解

爲了舉例說明@ConditionalOnProperty的用法,接下來開發一個基本的通知系統。 爲了使事情現在變得簡單,假設要發送電子郵件通知。

首先,需要創建一個簡單的服務來發送通知消息。 例如,考慮NotificationSender接口:

public interface NotificationSender {
    String send(String message);
}

接下來,提供NotificationSender接口的實現,以發送電子郵件:

public class EmailNotification  implements NotificationSender {
    @Override
    public String send(String message) {
        return "Email Notification: " + message;
    }
}

現在,看看如何使用@ConditionalOnProperty註解。 以這樣的方式配置NotificationSender Bean,使其僅在定義了屬性notification.service時才加載:

@Bean(name = "emailNotification")
@ConditionalOnProperty(prefix = "notification", name = "service")
public NotificationSender notificationSender() {
    return new EmailNotification();
}

prefix和name屬性用於表示應檢查的配置屬性。

最後,需要在application.properties文件中定義的自定義屬性:

notification.service=email

4、高級配置

正如前面已經瞭解的那樣,@ConditionalOnProperty註解允許根據配置屬性的存在條件有條件地註冊bean。

使用此註釋,可以做更多的事情。

假設要添加另一個通知服務,例如,一個允許發送SMS通知的服務。

爲此,需要創建另一個NotificationSender實現:

public class SmsNotification implements NotificationSender {
    @Override
    public String send(String message) {
        return "SMS Notification: " + message;
    }
}

由於有兩個實現,看看如何使用@ConditionalOnProperty有條件地加載正確的NotificationSender bean。

註解提供了havingValue屬性。 非常有趣的是,它定義了一個屬性必須具有的值,以便將特定的Bean添加到Spring容器中。

現在,指定要在什麼條件下在上下文中註冊SmsNotification實現:

@Bean(name = "smsNotification")
@ConditionalOnProperty(prefix = "notification", name = "service", havingValue = "sms")
public NotificationSender notificationSender2() {
    return new SmsNotification();
}
    

藉助於hadingValue屬性,清楚地表明,僅當notification.service設置爲sms時,才希望加載SmsNotification。

@ConditionalOnProperty具有另一個名爲matchIfMissing的屬性。 此屬性指定在屬性不可用的情況下條件是否應匹配。

單元測:

public class NotificationUnitTest {

    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();

    @Test
    public void sender() {
        this.contextRunner.withPropertyValues("notification.service=email")
                .withUserConfiguration(NotificationConfig.class)
                .run(context -> {
                    assertThat(context).hasBean("emailNotification");
                    NotificationSender notificationSender = context.getBean(EmailNotification.class);
                    assertThat(notificationSender.send("Hello From spring!")).isEqualTo("Email Notification: Hello From spring!");
                    assertThat(context).doesNotHaveBean("smsNotification");
                });
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章