Micronaut 使用@EachProperty 驱动配置

2023-03-01 16:16 更新

@ConfigurationProperties 注释非常适合单个配置类,但有时您需要多个实例,每个实例都有自己独特的配置。这就是 EachProperty 的用武之地。

@EachProperty 注释为给定名称中的每个子属性创建一个 ConfigurationProperties bean。作为示例,请考虑以下类:

使用@EachProperty

 Java Groovy  Kotlin 
import java.net.URI;
import java.net.URISyntaxException;

import io.micronaut.context.annotation.Parameter;
import io.micronaut.context.annotation.EachProperty;

@EachProperty("test.datasource")  // (1)
public class DataSourceConfiguration {

    private final String name;
    private URI url = new URI("localhost");

    public DataSourceConfiguration(@Parameter String name) // (2)
            throws URISyntaxException {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public URI getUrl() { // (3)
        return url;
    }

    public void setUrl(URI url) {
        this.url = url;
    }
}
import io.micronaut.context.annotation.EachProperty
import io.micronaut.context.annotation.Parameter

@EachProperty("test.datasource") // (1)
class DataSourceConfiguration {

    final String name
    URI url = new URI("localhost") // (3)

    DataSourceConfiguration(@Parameter String name) // (2)
            throws URISyntaxException {
        this.name = name
    }
}
import io.micronaut.context.annotation.EachProperty
import io.micronaut.context.annotation.Parameter
import java.net.URI
import java.net.URISyntaxException

@EachProperty("test.datasource")  // (1)
class DataSourceConfiguration
@Throws(URISyntaxException::class)
constructor(@param:Parameter val name: String) { // (2)
    var url = URI("localhost") // (3)
}
  1. @EachProperty 注解定义了要处理的属性名。

  2. @Parameter注解可用于注入定义bean名称的子属性名称(也是bean限定符)

  3. bean 的每个属性都绑定到配置。

上面的 DataSourceConfiguration 定义了一个 url 属性来配置一个或多个数据源。可以使用对 Micronaut 评估的任何 PropertySource 实例配置 URL 本身:

向@EachProperty 提供配置

 Java Groovy  Kotlin 
ApplicationContext applicationContext = ApplicationContext.run(PropertySource.of(
        "test",
        CollectionUtils.mapOf(
                "test.datasource.one.url", "jdbc:mysql://localhost/one",
                "test.datasource.two.url", "jdbc:mysql://localhost/two")
));
ApplicationContext applicationContext = ApplicationContext.run(PropertySource.of(
        "test",
        [
                "test.datasource.one.url": "jdbc:mysql://localhost/one",
                "test.datasource.two.url": "jdbc:mysql://localhost/two"
        ]
))
val applicationContext = ApplicationContext.run(PropertySource.of(
        "test",
        mapOf(
                "test.datasource.one.url" to "jdbc:mysql://localhost/one",
                "test.datasource.two.url" to "jdbc:mysql://localhost/two"
        )
))

在上面的示例中,两个数据源(称为一和二)在前面定义的 @EachProperty 注释中的 test.datasource 前缀下定义。这些配置条目中的每一个都会触发新的 DataSourceConfiguration bean 的创建,以便以下测试成功:

评估由@EachProperty 构建的 Bean

 Java Groovy  Kotlin 
Collection<DataSourceConfiguration> beansOfType = applicationContext.getBeansOfType(DataSourceConfiguration.class);
assertEquals(2, beansOfType.size()); // (1)

DataSourceConfiguration firstConfig = applicationContext.getBean(
        DataSourceConfiguration.class,
        Qualifiers.byName("one") // (2)
);

assertEquals(
        new URI("jdbc:mysql://localhost/one"),
        firstConfig.getUrl()
);
when:
Collection<DataSourceConfiguration> beansOfType = applicationContext.getBeansOfType(DataSourceConfiguration.class)
assertEquals(2, beansOfType.size()) // (1)

DataSourceConfiguration firstConfig = applicationContext.getBean(
        DataSourceConfiguration.class,
        Qualifiers.byName("one") // (2)
)

then:
new URI("jdbc:mysql://localhost/one") == firstConfig.getUrl()
val beansOfType = applicationContext.getBeansOfType(DataSourceConfiguration::class.java)
assertEquals(2, beansOfType.size) // (1)

val firstConfig = applicationContext.getBean(
        DataSourceConfiguration::class.java,
        Qualifiers.byName("one") // (2)
)

assertEquals(
        URI("jdbc:mysql://localhost/one"),
        firstConfig.url
)
  1. 可以使用 getBeansOfType 检索所有 DataSourceConfiguration 类型的 beans

  2. 可以使用 byName 限定符检索单个 bean。

基于列表的绑定

@EachProperty 的默认行为是从映射样式的配置进行绑定,其中键是 bean 的命名限定符,值是要绑定的数据。对于地图样式配置没有意义的情况,可以通知 Micronaut 该类是从列表中绑定的。只需将注释上的列表成员设置为 true。

@EachProperty 列表示例

 Java Groovy  Kotlin 
import io.micronaut.context.annotation.EachProperty;
import io.micronaut.context.annotation.Parameter;
import io.micronaut.core.order.Ordered;

import java.time.Duration;

@EachProperty(value = "ratelimits", list = true) // (1)
public class RateLimitsConfiguration implements Ordered { // (2)

    private final Integer index;
    private Duration period;
    private Integer limit;

    RateLimitsConfiguration(@Parameter Integer index) { // (3)
        this.index = index;
    }

    @Override
    public int getOrder() {
        return index;
    }

    public Duration getPeriod() {
        return period;
    }

    public void setPeriod(Duration period) {
        this.period = period;
    }

    public Integer getLimit() {
        return limit;
    }

    public void setLimit(Integer limit) {
        this.limit = limit;
    }
}
import io.micronaut.context.annotation.EachProperty
import io.micronaut.context.annotation.Parameter
import io.micronaut.core.order.Ordered

import java.time.Duration

@EachProperty(value = "ratelimits", list = true) // (1)
class RateLimitsConfiguration implements Ordered { // (2)

    private final Integer index
    Duration period
    Integer limit

    RateLimitsConfiguration(@Parameter Integer index) { // (3)
        this.index = index
    }

    @Override
    int getOrder() {
        index
    }
}
import io.micronaut.context.annotation.EachProperty
import io.micronaut.context.annotation.Parameter
import io.micronaut.core.order.Ordered
import java.time.Duration

@EachProperty(value = "ratelimits", list = true) // (1)
class RateLimitsConfiguration
    constructor(@param:Parameter private val index: Int) // (3)
    : Ordered { // (2)

    var period: Duration? = null
    var limit: Int? = null

    override fun getOrder(): Int {
        return index
    }
}
  1. 注解的列表成员设置为true

  2. 如果在检索 bean 时顺序很重要,则实施 Ordered

  3. 索引被注入到构造函数中


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

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号