Micronaut 条件 Beans

2023-02-27 16:04 更新

有时您可能希望根据各种潜在因素(包括类路径、配置、其他 bean 的存在等)有条件地加载 bean。

Requires 注释提供了在 bean 上定义一个或多个条件的能力。

考虑以下示例:

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 定义了两个要求。第一个指示必须存在 DataSource bean 才能加载 bean。第二个要求确保在加载 JdbcBookService bean 之前设置 datasource.url 属性。

Kotlin 目前不支持可重复注解。当需要多个需求时使用@Requirements 注释。例如,@Requirements(Requires(… ), Requires(… ))。请参阅 https://youtrack.jetbrains.com/issue/KT-12794 以跟踪此功能。

如果多个 bean 需要相同的需求组合,您可以定义一个带有需求的元注释:

使用@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 注释:

使用元注解

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

如果您有多个 bean 需要在加载前满足给定要求,您可能需要考虑一个 bean 配置组,如下一节所述。

配置要求

@Requires 注解非常灵活,可用于多种用例。下表总结了一些可能性:

表 1. 使用 @Requires
需求 示例

要求存在一个或多个类

@Requires(classes=javax.servlet.Servlet)

要求缺少一个或多个类

@Requires(missing=javax.servlet.Servlet)

要求存在一个或多个 beans

@Requires(beans=javax.sql.DataSource)

要求不存在一个或多个 bean

@Requires(missingBeans=javax.sql.DataSource)

要求应用环境

@Requires(env="test")

要求环境不适用

@Requires(notEnv="test")

需要存在另一个配置包

@Requires(configuration="foo.bar")

要求不存在另一个配置包

@Requires(missingConfigurations="foo.bar")

需要特定的 SDK 版本

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

要求使用给定注释注释的类通过包扫描可供应用程序使用

@Requires(entities=javax.persistence.Entity)

需要具有可选值的属性

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

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

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

要求文件系统中存在一个或多个文件

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

要求存在一个或多个类路径资源

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

要求当前操作系统在列表中

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

要求当前操作系统不在列表中

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

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

@Requires(bean=Config.class)

需要存在指定的 bean 属性

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

关于属性要求的附加说明。

添加对属性的要求具有一些附加功能。您可以要求属性为特定值,而不是特定值,如果未设置,则在这些检查中使用默认值。

@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. 需要设置属性

  2. 要求属性为“John”

  3. 要求属性为“John”或未设置

  4. 要求属性不是“Sally”或未设置

在 @Requires 中引用 bean 属性。

您还可以在 @Requires 中引用其他 bean 属性以有条件地加载 bean。与属性要求类似,您可以指定所需的值或设置值 bean 属性不应等于使用 notEquals 注释成员。对于要检查的 bean 属性,bean 注释成员中指定类型的 bean 应该存在于上下文中,否则将不会加载条件 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. 需要设置 Config bean 的“foo”属性

  2. 要求 Config bean 上的“foo”属性为“John”

  3. 要求 Config bean 上的“foo”属性不是“Sally”或未设置

通过相应的 getter 方法访问指定的 bean 属性,这些方法的存在和可用性将在编译时检查。

请注意,如果 bean 属性的值不为空,则认为它存在。请记住,原始属性使用默认值初始化,例如布尔值的 false 和 int 的 0,因此即使没有为它们明确指定值,它们也被视为已设置。

调试条件 Bean

如果您有多个条件和复杂的要求,可能很难理解为什么没有加载特定的 bean。

为了帮助解决条件 bean 的问题,您可以为 io.micronaut.context.condition 包启用调试日志记录,它将记录 bean 未加载的原因。

logback.xml

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


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号