blog

Spring Extension-1-カスタム環境変数のバリデーション

言うまでもないことですが、公式のコメントを見て、キーメソッドの場所を特定できるはずです。 ご覧のように、スプリングコンテナの初期化は、コレクションからすべてのキーを取り出し、これらのキーを取得します....

Apr 14, 2020 · 4 min. read
Share this

この投稿では、カスタム環境変数のバリデーションを実装する方法を理解することから始めます。

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

要約すると、検証は完了し、サブクラスをカスタマイズすることで指定した環境変数を強制的に存在させることができます。

Read next

プログラミング言語の基礎

高級言語:人間の論理的思考の観点からあらゆるタイプのアプリケーションに対応するプログラミング言語で、抽象度がはるかに高く、実行する特定のマシン上でターゲットコードを呼び出すためのコンパイルが必要。このタイプの言語は、人間が使用する自然言語に近いため、プログラミングの効率が大幅に向上します。中間コードを、特定のマシン上で絶対コードまたは再配置可能な命令コードまたはアセンブリ命令コードに変換することです。コンパイルの最終段階。

Apr 14, 2020 · 6 min read