設定サポートの拡張
1. カスタム ConfigSource
MicroProfile Config で指定されたカスタム ConfigSource
を作成することが可能です。
カスタム ConfigSource
では、追加の設定値を読み込んで、定義された順序で Config
インスタンスに追加することができます。これにより、他のソースからの値をオーバーライドしたり、他の値にフォールバックしたりすることができます。
A custom ConfigSource
requires an implementation of org.eclipse.microprofile.config.spi.ConfigSource
or
org.eclipse.microprofile.config.spi.ConfigSourceProvider
. Each implementation requires registration via
the ServiceLoader mechanism, either in
META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource
or
META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider
files.
1.1. 例
単純なインメモリ ConfigSource
を考えてみましょう。
package org.acme.config;
import org.eclipse.microprofile.config.spi.ConfigSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class InMemoryConfigSource implements ConfigSource {
private static final Map<String, String> configuration = new HashMap<>();
static {
configuration.put("my.prop", "1234");
}
@Override
public int getOrdinal() {
return 275;
}
@Override
public Set<String> getPropertyNames() {
return configuration.keySet();
}
@Override
public String getValue(final String propertyName) {
return configuration.get(propertyName);
}
@Override
public String getName() {
return InMemoryConfigSource.class.getSimpleName();
}
}
そして以下に登録します。
org.acme.config.InMemoryConfigSource
InMemoryConfigSource
は、 275
の序列により、 .env
ソースと、 application.properties
ソースの間に順序付けられます。
ConfigSource | 序列 |
---|---|
システムプロパティ |
400 |
システムからの環境変数 |
300 |
|
295 |
InMemoryConfigSource |
275 |
|
260 |
アプリケーションからの |
250 |
アプリケーションからの |
100 |
この場合、 InMemoryConfigSource
からの my.prop
は、設定エンジンが システムプロパティ、 システムからの環境変数、 .env ファイルからの環境変数の順に値を見つけられない場合にのみ使用されます。
1.2. ConfigSource初期化
Quarkusアプリケーションの起動時に、 ConfigSource
を2回初期化することができます。1回目は STATIC INIT で、2回目は RUNTIME INIT です。
1.2.1. STATIC INIT
Quarkusは静的初期化中にいくつかのサービスを開始しますが、 Config
は通常、最初に作成されるものの1つです。特定の状況では、カスタムの ConfigSource
を追加できない場合があります。例えば、 ConfigSource
がデータベースアクセスのような他のサービスを必要とする場合、この段階では利用できず、鶏と卵の問題が発生してしまいます。このため、カスタム ConfigSource
には、この段階で使用しても安全であるとソースをマークするためのアノテーション @io.quarkus.runtime.configuration.StaticInitSafe
が必要です。
1.2.1.1. 例
以下だとすると、
package org.acme.config;
import org.eclipse.microprofile.config.spi.ConfigSource;
import io.quarkus.runtime.annotations.StaticInitSafe;
@StaticInitSafe
public class InMemoryConfigSource implements ConfigSource {
}
そして以下に登録します。
org.acme.config.InMemoryConfigSource
InMemoryConfigSource
は、 STATIC INIT 中に利用可能になります。
カスタム ConfigSource は、Quarkusの STATIC INIT 中に自動的に追加されません。 @io.quarkus.runtime.configuration.StaticInitSafe のアノテーションを付ける必要があります。
|
2. ConfigSourceFactory
ConfigSource
を作成するもう一つの方法は、 SmallRye Config io.smallrye.config.ConfigSourceFactory
API を使用することです。 SmallRye Configのファクトリーと、 MicroProfile Config で指定されている ConfigSource
を作成する標準的な方法との違いは、利用可能な構成にアクセスできるコンテキストを提供するファクトリーの機能です。
Each implementation of io.smallrye.config.ConfigSourceFactory
requires registration via
the ServiceLoader
mechanism in the META-INF/services/io.smallrye.config.ConfigSourceFactory
file.
2.1. 例
以下だとすると、
package org.acme.config;
import java.util.Collections;
import java.util.OptionalInt;
import org.eclipse.microprofile.config.spi.ConfigSource;
import io.smallrye.config.ConfigSourceContext;
import io.smallrye.config.ConfigSourceFactory;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.PropertiesConfigSource;
public class URLConfigSourceFactory implements ConfigSourceFactory {
@Override
public Iterable<ConfigSource> getConfigSources(final ConfigSourceContext context) {
final ConfigValue value = context.getValue("config.url");
if (value == null || value.getValue() == null) {
return Collections.emptyList();
}
try {
return Collections.singletonList(new PropertiesConfigSource(new URL(value.getValue())));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public OptionalInt getPriority() {
return OptionalInt.of(290);
}
}
そして以下に登録します。
org.acme.config.URLConfigSourceFactory
io.smallrye.config.ConfigSourceFactory
を実装することで、 Iterable<ConfigSource> getConfigSources(ConfigSourceContext context)
メソッドを介して ConfigSource
のリストを提供することができます。また、 ConfigSourceFactory
は、 OptionalInt getPriority()
メソッドをオーバーライドすることで、優先度を割り当てることができます。優先度の値は、複数の io.smallrye.config.ConfigSourceFactory
をソートするために使用されます(見つかった場合)。
io.smallrye.config.ConfigSourceFactory の優先順位は、 ConfigSource の序列には影響しません。これらは独立してソートされます。
|
ファクトリーの初期化中、提供された ConfigSourceContext
は、メソッド ConfigValue getValue(String name)
を呼び出すことができます。このメソッドは、 Config
インスタンスによってすでに初期化されたすべての ConfigSource`の設定名を検索します。これには、 `ConfigSourceFactory
で定義されたものよりも低い序列のソースが含まれます。 ConfigSourceFactory
によって提供された ConfigSource
リストは、優先順位の低い ConfigSourceFactory
によって生成された他のソースを構成するためには考慮されません。
3. カスタム Converter
MicroProfile Configで指定されたカスタム Converter
型を作成することが可能です。
A custom Converter
requires an implementation of org.eclipse.microprofile.config.spi.Converter<T>
. Each implementation
requires registration via the ServiceLoader
mechanism in the META-INF/services/org.eclipse.microprofile.config.spi.Converter
file. Consider:
package org.acme.config;
public class MicroProfileCustomValue {
private final int number;
public MicroProfileCustomValue(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
}
対応するコンバータは以下のようになります。
package org.acme.config;
import org.eclipse.microprofile.config.spi.Converter;
public class MicroProfileCustomValueConverter implements Converter<MicroProfileCustomValue> {
@Override
public MicroProfileCustomValue convert(String value) {
return new MicroProfileCustomValue(Integer.parseInt(value));
}
}
カスタム・コンバータ・クラスは public でなければならず、 public コンストラクタは引数なしでなければならず、 abstract であってはなりません。
|
カスタムコンフィグレーションタイプは、設定値を自動的に変換します。
@ConfigProperty(name = "configuration.value.name")
MicroProfileCustomValue value;
3.1. コンバーターの優先順位
jakarta.annotation.Priority
アノテーションは、 Converter
の優先順位を上書きし、コンバータの優先順位を変更して実行順序を微調整します。デフォルトでは、 Converter
に @Priority
が指定されていない場合、コンバーターは 100
の優先順位で登録されます。以下の場合、
package org.acme.config;
import jakarta.annotation.Priority;
import org.eclipse.microprofile.config.spi.Converter;
@Priority(150)
public class MyCustomConverter implements Converter<MicroProfileCustomValue> {
@Override
public MicroProfileCustomValue convert(String value) {
final int secretNumber;
if (value.startsFrom("OBF:")) {
secretNumber = Integer.parseInt(SecretDecoder.decode(value));
} else {
secretNumber = Integer.parseInt(value);
}
return new MicroProfileCustomValue(secretNumber);
}
}
同値の型 ( MicroProfileCustomValue
)を変換し、優先度が 150
であるため、デフォルトの優先度が 100
である MicroProfileCustomValueConverter
の代わりに使用されます。
すべてのQuarkusコアコンバーターは、 200 の優先値を使用しています。Quarkus特有のコンバーターをオーバーライドするには、優先度の値を 200 よりも高くする必要があります。
|
4. 設定インターセプター
SmallRye Configは、設定値の解決をフックするインターセプターチェーンを提供します。これは、 プロファイルや プロパティExpressionsのような機能を実装するのに便利で、また、設定値がどこから読み込まれたかを調べるためのロギングにも役立ちます。
An interceptor requires an implementation of io.smallrye.config.ConfigSourceInterceptor
. Each implementation
requires registration via the ServiceLoader
mechanism in the META-INF/services/io.smallrye.config.ConfigSourceInterceptor
file.
io.smallrye.config.ConfigSourceInterceptor
は、メソッド ConfigValue getValue(ConfigSourceInterceptorContext context, String name)
で設定名の解決をインターセプトすることができます。 ConfigSourceInterceptorContext
は、インターセプター・チェーンを進めるために使用されます。このチェーンは、 io.smallrye.config.ConfigValue
のインスタンスを返すことで短絡させることができます。 ConfigValue
オブジェクトは、キー名、値、コンフィグソースのオリジン、序列に関する情報を保持しています。
インターセプターチェーンは、設定値の変換が行われる前に適用されます。 |
Interceptors may also be created with an implementation of io.smallrye.config.ConfigSourceInterceptorFactory
. Each
implementation requires registration via the ServiceLoader
mechanism in the META-INF/services/io.smallrye.config.ConfigSourceInterceptorFactory
file.
ConfigSourceInterceptorFactory
は、(インターセプターの設定や設定値の取得に使用できるように)現在のチェーンにアクセスし、インターセプターを初期化し、優先度を設定することができます。
4.1. 例
package org.acme.config;
import static io.smallrye.config.SecretKeys.doLocked;
import jakarta.annotation.Priority;
import io.smallrye.config.ConfigSourceInterceptor;
import io.smallrye.config.ConfigLogging;
@Priority(Priorities.LIBRARY + 200)
public class LoggingConfigSourceInterceptor implements ConfigSourceInterceptor {
private static final long serialVersionUID = 367246512037404779L;
@Override
public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) {
ConfigValue configValue = doLocked(() -> context.proceed(name));
if (configValue != null) {
ConfigLogging.log.lookup(configValue.getName(), configValue.getLocation(), configValue.getValue());
} else {
ConfigLogging.log.notFound(name);
}
return configValue;
}
}
そして以下に登録します。
org.acme.config.LoggingConfigSourceInterceptor
LoggingConfigSourceInterceptor
ログは、提供されたログプラットフォームで設定名を検索します。ログ情報には、設定名と値、設定ソースの出所と場所(存在する場合)が含まれます。