この投稿では、カスタム環境変数のバリデーションを実装する方法を理解することから始めます。
Springのソースコード解析
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
getEnvironment().validateRequiredProperties();
言うまでもないことですが、公式ノートを見れば、キーとなるメソッドを見つけることができるはずです。
AbstractPropertyResolver;
validateRequiredProperties;
メソッドをトレースし続けると、最終的にクラスのメソッドに対応することがわかります。
public void validateRequiredProperties() {
MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
for (String key : this.requiredProperties) {
if (this.getProperty(key) == null) {
ex.addMissingRequiredProperty(key);
}
}
if (!ex.getMissingRequiredProperties().isEmpty()) {
throw ex;
}
}
ご覧のように、スプリングコンテナが初期化されると、requiredPropertiesコレクションからすべてのキーを取り出し、これらのキーの環境変数を取得します。 キーの1つに対応する環境変数がNULLの場合、例外がスローされ、スプリングコンテナの初期化は失敗します。
拡張関数解析
要約すると、必要なバリデーション機能は、バリデーションされる環境変数のキーを requiredProperties コレクションに格納することで実現できることがわかりました。そして、それをいつどのように格納するかが解決すべき問題となります:
環境変数のキーを requiredProperties コレクションに格納する方法
AbstractPropertyResolver;
のsetRequiredProperties;
他のメソッドを見ると、requiredPropertiesを設定するために使用されていることがわかります:public void setRequiredProperties(String... requiredProperties) { Collections.addAll(this.requiredProperties, requiredProperties); }
AbstractPropertyResolver;
setRequiredProperties;
どの時点で、キーを設定するクラスのメソッドを実行するのですか?
AbstractApplicationContext;
クAbstractPropertyResolver;
setRequiredProperties;
ラスの initPropertySources メソッドをオーバーライドするサブクラスを作成します。
実習
開発とテストを容易にするために、練習の拡張はSpringBootフレームワークの下で行われます。
CustomApplicationContext;
AnnotationConfigServletWebServerApplicationContext;
initPropertySources メソッドを継承し、オーバーライドするクラスを作成します。
public class CustomApplicationContext extends AnnotationConfigServletWebServerApplicationContext {
@Override
protected void initPropertySources() {
super.initPropertySources();
//把"MYSQL_HOST"起動時に検証されなければならない環境変数として
getEnvironment().setRequiredProperties("MYSQL_HOST");
}
}
ApplicationContextのクラスをCustomApplicationContextに指定して、アプリケーション起動クラスApplicationを作成します:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(Application.class);
springApplication.setApplicationContextClass(CustomApplicationContext.class);
springApplication.run(args);
}
}
Mavenを使用してパッケージ化し、対応するjarパッケージを取得します:spring-0.0.1-SNAPSHOT.jar
java -jar spring-0.0.1-SNAPSHOT.jar
次に、環境変数の検証機能が実装されていることを確認するために、ターゲットディレクトリで:を実行すると、アプリケーションの起動に失敗し、ログに環境変数「MYSQL_HOST」が見つからなかったことが表示されます。
org.springframework.core.env.MissingRequiredPropertiesException: The following properties were declared as required but could not be resolved: [MYSQL_HOST]
以下のコマンドを実行すると、プロセス環境変数に「MYSQL_HOST」が設定され、今度はチェックをパスしてアプリケーションが正常に起動します。
java -D MYSQL_HOST="192.168.0.3" -jar spring-0.0.1-SNAPSHOT.jar
要約すると、検証は完了し、サブクラスをカスタマイズすることで指定した環境変数を強制的に存在させることができます。