Micronaut 條件 Beans

2023-02-27 16:04 更新

有時(shí)您可能希望根據(jù)各種潛在因素(包括類(lèi)路徑、配置、其他 bean 的存在等)有條件地加載 bean。

Requires 注釋提供了在 bean 上定義一個(gè)或多個(gè)條件的能力。

考慮以下示例:

Using @Requires

 Java Groovy  Kotlin 
@Singleton
@Requires(beans = DataSource.class)
@Requires(property = "datasource.url")
public class JdbcBookService implements BookService {

    DataSource dataSource;

    public JdbcBookService(DataSource dataSource) {
        this.dataSource = dataSource;
    }
@Singleton
@Requires(beans = DataSource)
@Requires(property = "datasource.url")
class JdbcBookService implements BookService {

    DataSource dataSource
@Singleton
@Requirements(Requires(beans = [DataSource::class]), Requires(property = "datasource.url"))
class JdbcBookService(internal var dataSource: DataSource) : BookService {

上面的 bean 定義了兩個(gè)要求。第一個(gè)指示必須存在 DataSource bean 才能加載 bean。第二個(gè)要求確保在加載 JdbcBookService bean 之前設(shè)置 datasource.url 屬性。

Kotlin 目前不支持可重復(fù)注解。當(dāng)需要多個(gè)需求時(shí)使用@Requirements 注釋。例如,@Requirements(Requires(… ), Requires(… ))。請(qǐng)參閱 https://youtrack.jetbrains.com/issue/KT-12794 以跟蹤此功能。

如果多個(gè) bean 需要相同的需求組合,您可以定義一個(gè)帶有需求的元注釋?zhuān)?

使用@Requires 元注解

 Java  Groovy Kotlin 
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PACKAGE, ElementType.TYPE})
@Requires(beans = DataSource.class)
@Requires(property = "datasource.url")
public @interface RequiresJdbc {
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target([ElementType.PACKAGE, ElementType.TYPE])
@Requires(beans = DataSource)
@Requires(property = "datasource.url")
@interface RequiresJdbc {
}
@Documented
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FILE)
@Requirements(Requires(beans = [DataSource::class]), Requires(property = "datasource.url"))
annotation class RequiresJdbc

在上面的示例中,可以在 JdbcBookService 上使用 RequiresJdbc 注釋?zhuān)?

使用元注解

@RequiresJdbc
public class JdbcBookService implements BookService {
    ...
}

如果您有多個(gè) bean 需要在加載前滿(mǎn)足給定要求,您可能需要考慮一個(gè) bean 配置組,如下一節(jié)所述。

配置要求

@Requires 注解非常靈活,可用于多種用例。下表總結(jié)了一些可能性:

表 1. 使用 @Requires
需求 示例

要求存在一個(gè)或多個(gè)類(lèi)

@Requires(classes=javax.servlet.Servlet)

要求缺少一個(gè)或多個(gè)類(lèi)

@Requires(missing=javax.servlet.Servlet)

要求存在一個(gè)或多個(gè) beans

@Requires(beans=javax.sql.DataSource)

要求不存在一個(gè)或多個(gè) bean

@Requires(missingBeans=javax.sql.DataSource)

要求應(yīng)用環(huán)境

@Requires(env="test")

要求環(huán)境不適用

@Requires(notEnv="test")

需要存在另一個(gè)配置包

@Requires(configuration="foo.bar")

要求不存在另一個(gè)配置包

@Requires(missingConfigurations="foo.bar")

需要特定的 SDK 版本

@Requires(sdk=Sdk.JAVA, value="1.8")

要求使用給定注釋注釋的類(lèi)通過(guò)包掃描可供應(yīng)用程序使用

@Requires(entities=javax.persistence.Entity)

需要具有可選值的屬性

@Requires(property="data-source.url")

要求屬性不屬于配置的一部分

@Requires(missingProperty="data-source.url")

要求文件系統(tǒng)中存在一個(gè)或多個(gè)文件

@Requires(resources="file:/path/to/file")

要求存在一個(gè)或多個(gè)類(lèi)路徑資源

@Requires(resources="classpath:myFile.properties")

要求當(dāng)前操作系統(tǒng)在列表中

@Requires(os={Requires.Family.WINDOWS})

要求當(dāng)前操作系統(tǒng)不在列表中

@Requires(notOs={Requires.Family.WINDOWS})

如果未指定 beanProperty,則需要存在 bean

@Requires(bean=Config.class)

需要存在指定的 bean 屬性

@Requires(bean=Config.class, beanProperty="enabled")

關(guān)于屬性要求的附加說(shuō)明。

添加對(duì)屬性的要求具有一些附加功能。您可以要求屬性為特定值,而不是特定值,如果未設(shè)置,則在這些檢查中使用默認(rèn)值。

@Requires(property="foo") (1)
@Requires(property="foo", value="John") (2)
@Requires(property="foo", value="John", defaultValue="John") (3)
@Requires(property="foo", notEquals="Sally") (4)
  1. 需要設(shè)置屬性

  2. 要求屬性為“John”

  3. 要求屬性為“John”或未設(shè)置

  4. 要求屬性不是“Sally”或未設(shè)置

在 @Requires 中引用 bean 屬性。

您還可以在 @Requires 中引用其他 bean 屬性以有條件地加載 bean。與屬性要求類(lèi)似,您可以指定所需的值或設(shè)置值 bean 屬性不應(yīng)等于使用 notEquals 注釋成員。對(duì)于要檢查的 bean 屬性,bean 注釋成員中指定類(lèi)型的 bean 應(yīng)該存在于上下文中,否則將不會(huì)加載條件 bean。

@Requires(bean=Config.class, beanProperty="foo") (1)
@Requires(bean=Config.class, beanProperty="foo", value="John") (2)
@Requires(bean=Config.class, beanProperty="foo", notEquals="Sally") (3)
  1. 需要設(shè)置 Config bean 的“foo”屬性

  2. 要求 Config bean 上的“foo”屬性為“John”

  3. 要求 Config bean 上的“foo”屬性不是“Sally”或未設(shè)置

通過(guò)相應(yīng)的 getter 方法訪問(wèn)指定的 bean 屬性,這些方法的存在和可用性將在編譯時(shí)檢查。

請(qǐng)注意,如果 bean 屬性的值不為空,則認(rèn)為它存在。請(qǐng)記住,原始屬性使用默認(rèn)值初始化,例如布爾值的 false 和 int 的 0,因此即使沒(méi)有為它們明確指定值,它們也被視為已設(shè)置。

調(diào)試條件 Bean

如果您有多個(gè)條件和復(fù)雜的要求,可能很難理解為什么沒(méi)有加載特定的 bean。

為了幫助解決條件 bean 的問(wèn)題,您可以為 io.micronaut.context.condition 包啟用調(diào)試日志記錄,它將記錄 bean 未加載的原因。

logback.xml

<logger name="io.micronaut.context.condition" level="DEBUG"/>


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)