@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)
}
|
@EachProperty 注解定义了要处理的属性名。
@Parameter注解可用于注入定义bean名称的子属性名称(也是bean限定符)
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
)
|
可以使用 getBeansOfType 检索所有 DataSourceConfiguration 类型的 beans
可以使用 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
}
}
|
注解的列表成员设置为true
如果在检索 bean 时顺序很重要,则实施 Ordered
索引被注入到构造函数中
更多建议: