M12i.

学術書・マンガ・アニメ・映画の消費活動とプログラミングについて

『Spring Bootリファレンス・ガイド』より第4部「Spring Boot の重要機能」(1)

例によってあまり脈絡がないけれどSpring Bootについて興味があったのでリファレンス・ガイドを参照しています。先頭から読んでいくとらちが明かないので、いきなり第4章「Spring Boot の重要機能」("Part IV. Spring Boot features")から。これも例によって興味のあるところだけの訳出です。

まずはSpringApplicationによるアプリケーションのブート、外部化されたコンフィギュレーションとプロファイルによる設定情報の隔離、そしてロギングまで。原典は"Spring Boot Reference Guide"(1.1.8.RELEASE版。2014/10/28取得)の"Part IV. Spring Boot features"です。

          * * *

Spring Boot の重要機能

このセクションではSpring Bootの詳細に飛び込んでいきます。このセクションの中で、あなたが使いたいと思う重要機能、カスタマイズしたいと思う重要機能について学ぶことができるでしょう。もしまだでしたら、'Part II, “Getting started”' と 'Part III, “Using Spring Boot”'に先に目を通しておいたほうが良いかもしれません。これらのセクションでは基本的な事項について学ぶことができます。

20. SpringApplication

SpringApplicationクラスmain()メソッドからSpringアプリケーションを起動するのに便宜を提供します。多くの場合、あなたは静的メソッドSpringApplication.runに処理を委譲するだけで済みます:

public static void main(String[] args) {
    SpringApplication.run(MySpringConfiguration.class, args);
}

アプリケーションが起動すると下記のような出力を目にすることになるでしょう:

f:id:m12i:20141028091341p:plain

デフォルトではINFOログ・メッセージが表示されます。このメッセージは例えばアプリケーションを起動したユーザなどの起動に関連する詳細情報を含んでいます。

20.1 バナーをカスタマイズする

開始時に表示されるバナー〔訳注:前述のアスキーアートのこと〕はクラスパスにbanner.txtファイルを作成するか、かbanner.locationプロパティが指すパスにファイルを配置することで変更可能です。もしファイルが一般的でないエンコーディングで記述されている場合はbanner.encodingプロパティで指定することが可能です(デフォルトはUTF-8です)。

20.2 SpringApplication をカスタマイズする

SpringApplicationのデフォルトの動作があなたの望みに沿わない場合、インスタンス化をして、カスタマイズすることが可能です。例えば、バナー表示を止めさせたい場合はこのように書くことができます:

public static void main(String[] args) {
    SpringApplication app = new SpringApplication(MySpringConfiguration.class);
    app.setShowBanner(false);
    app.run(args);
}


[NOTE] SpringApplicationに渡されるコンストラクタ引数は、Springビーンの定義元です。ほとんどのケースでは@Configurationアノテーションが付与されたクラス群を指すものになるでしょう。しかしXMLコンフィギュレーションや設定情報をスキャンすべきパッケージを指すオブジェクトを指定することも可能です。

SpringApplicationの設定にはapplication.propertiesファイルを使うことも可能です。詳細については'Chapter 21, Externalized Configuration'を参照してください。

設定可能なオプションの完全なリストについてはSpringApplicationJavadocを参照してください。

20.3 FluentビルダーAPI

ApplicationContext階層構造(親子関係を持つ複数のコンテキスト)を構築したいという場合、あるいは‘fluent’〔訳注:Fluent Interfaceを指している〕ビルダーAPIを単に用いたいという場合、SpringApplicationBuilderクラスを使用することができます。

SpringApplicationBuilderクラスは複数メソッド呼び出しをチェインさせることを可能にする一方、階層構造をつくるためのparentメソッドchildメソッドを提供しています。
例えば:

new SpringApplicationBuilder()
    .showBanner(false)
    .sources(Parent.class)
    .child(Application.class)
    .run(args);


[NOTE] ApplicationContext階層構造をつくる場合いくつかの制約があります。例えば、Webコンポーネントは子ども側のコンテキストに含まれていなくてはなりません。加えて、 同じEnvironment〔訳注:Springフレームワーク内部で使用されているインターフェースで、実行中のアプリケーションの設定情報を保持している〕が親側でも子ども側でも使用されている必要があります。詳細についてはSpringApplicationBuilderJavadocを参照してください。

20.4 アプリケーション・イベントとリスナー

ContextRefreshedEventのような便利なSpringフレームワーク・イベントに加えて、SpringApplicationクラスはいくつかのアプリケーション・イベントを発生させます。いくつかのイベントはApplicationContextが生成されるよりも前に生起されます。
イベント・リスナーはいくつかの方法で登録できますが、もっとも一般的な方法はSpringApplication.addListeners(…)メソッドを使用する方法です。

アプリケーションが起動されると、アプリケーション・イベントは以下の順序で発生します:

  1. アプリケーションが起動されるとApplicationStartedEventが発生します。これはリスナーの登録と初期化を除くいかなる処理よりも先んじて発生します。
  2. ApplicationEnvironmentPreparedEventは起動したアプリケーションのコンテキストにおいて使用されるEnvironmentが確認されたあと、ただしコンテキストそのものが生成されるよりも前に発生します。
  3. ApplicationPreparedEventはリフレッシュ〔訳注:コンフィギュレーションにしたがってビーン=オブジェクトが初期化される?〕が開始される直前、ただし定義の読み込み自体は完了したあとに発生します。
  4. ApplicationFailedEventは起動処理中に例外がスローされた場合に発生します。


[NOTE] アプリケーション・イベントを使用しなくてはいけないケースにはあまり出会わないでしょう。しかしそれが存在することを知るのは簡単です。内部的には、Spring Bootはイベントをさまざまなタスクを制御するのに使用しています。

20.5 Webアプリケーションかそうでないか

SpringApplicationはあなたに代わって正しいApplicationContextを生成しようと試みます。デフォルトでは、AnnotationConfigApplicationContextクラスもしくはAnnotationConfigEmbeddedWebApplicationContextクラスが使用されます。2つのうちいずれになるかは、あなたが開発しているのがWebアプリケーションかどうかによって決まります。

これを決めるアルゴリズムは極めて単純です(いくつかのクラスが存在するかどうかで決まります)。デフォルトの動作を上書きしたい場合はsetWebEnvironment(boolean webEnvironment)メソッドが利用できます。

もちろんsetApplicationContextClass(…)メソッド呼び出しにより、使用されるべきApplicationContextについて完全にコントロールすることも可能です。

[NOTE]JUnitのテストコード内でSpringApplicationを使用する場合、setWebEnvironment(false)メソッド呼び出しを行うことが望ましいことがしばしばあります。

20.6 CommandLineRunner を使用する

生のコマンドライン引数にアクセスしたい場合や、SpringApplicationが起動したあと一度特定のコードを実行する必要がある場合、CommandLineRunnerインターフェースを実装することができます。このインターフェースを実装したSpringビーンはみなrun(String… args)メソッドが呼び出されます。

import org.springframework.boot.*
import org.springframework.stereotype.*

@Component
public class MyBean implements CommandLineRunner {

    public void run(String... args) {
        // Do something...
    }

}

これに加えてorg.springframework.core.Orderedインターフェースを実装するか、org.springframework.core.annotation.Orderアノテーションを使用することで、複数CommandLineRunnerビーンについてそれらのメソッドが呼び出される順序を指定できます。

20.7 アプリケーションの終了

SpringApplicationはアプリケーションの終了時にApplicationContextが確実にクローズされるようJVMのシャットダウン・フックを登録します。Springのライフサイクルにしたがってコールバック(例えばDisposableBeanインターフェースや@PreDestroyアノテーションにより定義される)が呼び出されます。

加えてorg.springframework.boot.ExitCodeGeneratorを実装することで、アプリケーション終了時に特定のExit Codeを返すようにすることもできます。

21. 外部化されたコンフィギュレーション

Spring Bootは外部化されたコンフィギュレーションもサポートしています。これによって、同じアプリケーション・コードを異なる環境で動かすことが可能になります。形式としては、プロパティ・ファイル、YAMLファイル、環境変数、そしてコマンドライン引数が使用できます。プロパティ値は、@Valueアノテーションを使用して直接ビーンのフィールドに注入させることも、SpringのEnvironmentを通じてアクセスすることも、構造化されたオブジェクトにバインドさせることも可能です。

Spring Bootはプロパティ値の上書きを考慮して非常に限定された順序でPropertySourceをロードします。プロパティは以下の優先度で処理されます:

  1. コマンドライン引数
  2. Javaシステム・プロパティ(System.getProperties()
  3. OS環境変数
  4. java:comp/env由来のJNDI属性
  5. random.*系のプロパティを提供するRandomValuePropertySource
  6. jarパッケージ外部のアプリケーション・プロパティ(YAMLやプロファイル・ヴァリアントを含むapplication.properties)
  7. jarパッケージ内部のアプリケーション・プロパティ(YAMLやプロファイル・ヴァリアントを含むapplication.properties)
  8. @Configurationクラスの@PropertySourceアノテーション
  9. デフォルト・プロパティ(SpringApplication.setDefaultPropertiesで指定される)

具体的な例を示すため、nameプロパティを使用する@Componentクラスを開発中であると仮定してみます:

import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*

@Component
public class MyBean {

    @Value("${name}")
    private String name;

    // ...

}

jar内部のapplication.propertiesファイルを使ってデフォルトのnameプロパティを指定することができます。本番稼働の際には、jar外部のapplication.propertiesファイルを使ってnameプロパティを上書きできます。そしてちょっとした動作検証のために、特定のコマンドライン・スイッチとともにアプリケーションを起動することもできます(例えば、java -jar app.jar --name="Spring")。

RandomValuePropertySourceはランダムな値を指定するのに便利です(例えば、シークレット値を指定したり、テスト・ケースのパラメータを供給するときなど)。このクラスは整数、長整数そして文字列を生成します。例えば:

my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}

random.int*の構文は OPEN value (,max) CLOSEで、OPENCLOSEは何らかの文字〔訳注:ようするに丸括弧でもブラケットでも何でもよいらしい〕、そしてvalue,maxは整数値です。maxが指定されている場合、valueは最小値となり、maxは最大値(maxの値は含まれない)となります。

21.1 コマンドライン・プロパティにアクセスする

デフォルトではSpringApplicationはいかなるコマンドライン・オプション引数(例えば--server.port=9000のように‘--’ではじまるもの)もプロパティに変換して、それをSpringのEnvironmentに登録します。前述の通り、このコマンドライン由来のプロパティは他のいずれの方法で定義されたプロパティよりも優先されます。

コマンドライン・プロパティをEnvironmentに登録させたくない場合、SpringApplication.setAddCommandLineProperties(false)とすることで無効化できます。

21.2 アプリケーション・プロパティ・ファイル

SpringApplicationは次の場所からapplication.propertiesを検索してロードし、SpringのEnvironmentに登録します:

  1. カレントディレクトリの/configサブディレクトリ
  2. カレントディレクトリ
  3. クラスパス内の/config配下
  4. クラスパスのroot

このリストは優先度の高い順です(上方のもので定義された値は下方のもので定義された値を上書きします)。

[NOTE]'.properties'ファイルの代わりにYAML('.yml')ファイルを使用することもできます。

コンフィギュレーション・ファイルの名前としてapplication.propertiesが好ましくない場合は、spring.config.nameプロパティで別の名前を指定することができます。加えて、spring.config.locationプロパティで明示的にファイルの格納された場所を指定することもできます(ディレクトリ・パスもしくはファイル・パスをCSV形式で並べたリスト)。

$ java -jar myproject.jar --spring.config.name=myproject

もしくは

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

spring.config.locationにディレクトリ・パスを含める場合は/で終える表記にする必要があります(このディレクトリ・パスには、実際にプロパティがロードされるに先立ち、spring.config.nameから導出されたファイル名が末尾に追加されます)。spring.config.locationに設定された値とはかかわりなく、デフォルトの検索パスとしていつもclasspath:、classpath:/config、file:、 file:configが使用されます。このような仕組みのため、application.properties(あるいはspring.config.nameで指定した別のファイル名のプロパティ・ファイル)でデフォルト値を設定し、実行時にはそれを別のファイルで上書きするということが可能になります。デフォルト値は〔訳注:実行時に有効であれ無効であれ〕常に保持されるのです。

[NOTE]システム・プロパティ以外のアプリケーション独自の値の定義に環境変数を利用する場合、ほとんどのOSではピリオドで区切られたキー名を使うことは不可能です。代わりにアンダースコアを使用します(例えばspring.config.nameの代わりにSPRING_CONFIG_NAMEを使います)。

[NOTE]コンテナでアプリケーションを実行する場合、JNDIプロパティ(java:comp/env形式で指定される)やサーブレット・コンテキスト初期化パラメータによるプロパティの指定が可能です。環境変数やシステム・プロパティももちろん利用可能です。

21.3 プロファイル固有のプロパティ

application.propertiesとは別に、application-{profile}.propertiesという命名規約を使用してプロファイル固有のプロパティを定義することができます。

プロファイル固有のプロパティは標準的なapplication.propertiesの格納場所と同じ場所からロードされます。プロファイル固有のファイルの内容は、デフォルトのそれを上書きします。

21.4 プロパティ内のプレースホルダ

application.propertiesで定義された値は、それが使用される際にEnvironmentに登録済みの値でフィルタされ、予め定義された値(例えばシステム・プロパティなど)を参照することが可能です。

app.name=MyApp
app.description=${app.name} is a Spring Boot application


[NOTE]このテクニックを使って既存のSpring Bootプロパティに対する短縮版のヴァリアント〔訳注:つまりはエイリアス〕をつくることも可能です。詳細については'Section 58.3, “Use ‘short’ command line arguments”'を参照してください。

21.5 プロパティ・ファイルの代わりにYAMLを使う

(興味がないのでパス)

21.6 型安全なプロパティ定義

プロパティをビーンのフィールドに設定するために@Value("${property}")アノテーションを使用する方法はしばしば厄介な事態を引き起こします。とりわけ、複数値をとるプロパティや階層構造を持つデータを定義する場合がそうです。Spring Bootはこれに代わり、プロパティを定義するためしっかり型付けされたビーンを利用する方法を用意しています。例えば:

@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {

    private String username;

    private InetAddress remoteAddress;

    // ... getters and setters

}

@Configuration クラスに@EnableConfigurationPropertiesアノテーションが適用されている場合、@ConfigurationPropertiesアノテーションで印付されたすべてのビーンがEnvironmentに登録されたプロパティ情報で自動的に初期化されます。このコンフィギュレーション・スタイルはとくにYAMLによる外部化されたコンフィギュレーションによく調和します:

# application.yml

connection:
    username: admin
    remoteAddress: 192.168.1.1

# additional configuration as required

@ConfigurationPropertiesで印付けられたビーンを利用するには、他のビーンを利用するのと同様にして依存性注入の機能を利用するだけです。

@Service
public class MyService {

    @Autowired
    private ConnectionSettings connection;

     //...

    @PostConstruct
    public void openConnection() {
        Server server = new Server();
        this.connection.configure(server);
    }

}

@ConfigurationPropertiesアノテーションで印付けする方法に対する簡略版として、@EnableConfigurationPropertiesアノテーションのパラメータとして直接プロパティ値を設定するクラスのリストを指定する方法も利用可能です:

@Configuration
@EnableConfigurationProperties(ConnectionSettings.class)
public class MyConfiguration {
}

21.6.1 緩いバインディング〔Relaxed binding〕

Environment に登録されたプロパティを@ConfigurationProperties で印付けされたビーンにバインドするにあたり、Spring Bootはいくつかの緩いルールを利用します。つまりEnvironmentに登録されたプロパティの名前とビーンのプロパティの名前〔訳注:JavaBeansプロパティ≒フィールドの名前〕は正確に一致している必要はないということです。一般的な例としては、アンダースコアで区切られた名前(例えばcontext_pathcontextPathにバインドされる)や、キャピタライズされた名前(例えばPORTportにバインドされる)などがそうです。

@ConfigurationProperties で印付けされたビーンに外部アプリケーション・プロパティをバインドするにあたり、Springフレームワークはそれを正しい型になんとか割り当てようとします。独自の型変換を定義する必要がある場合、ConversionServiceビーン(ビーンIDとしてはconversionServiceになりますが)を使うか、独自のプロパティ・エディタ(CustomEditorConfigurerビーンによる)を使うことが可能です。

21.6.2 @ConfigurationProperties のバリデーション

Spring Bootは外部化されたコンフィギュレーションをバリデーションにかける際、デフォルトでJSR-303(それがクラスパスにあれば)を使用します。バリデーションを利用したい場合は、JSR-303で定義されている javax.validation制約アノテーションをあなたの定義した@ConfigurationPropertiesクラスに付与するだけです:

@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {

    @NotNull
    private InetAddress remoteAddress;

    // ... getters and setters

}

configurationPropertiesValidatorというIDを持つビーンを定義することで、 独自にSpringフレームワークValidatorを利用することも可能です。

[NOTE] spring-boot-actuatorモジュールはすべての@ConfigurationPropertiesビーンに対するアクセスのエンドポイントを含んでいます。あなたのWebブラウザで/configpropsを参照するか、これと同等のJMXエンドポイントを使用してみてください。詳細については'Production ready features'セクションを参照してください。

22. プロファイル

Springのプロファイルはアプリケーションの設定を部分ごとに隔離して、特定の環境においてのみ有効であるようにする方法を提供します。@Componentアノテーション@Configurationアノテーションが付与されたビーンに@Profileアノテーションで印をつけることで、それらがいつロードされるべきかを限定することができます。

@Configuration
@Profile("production")
public class ProductionConfiguration {

    // ...

}

一般的にSpringで使用される方法では、spring.profiles.activeプロパティによってどのプロファイルがアクティブなのかを指定します。このプロパティを指定する方法については問われません。例えば、application.propertiesファイルに記載しておくことも可能ですし:

spring.profiles.active=dev,hsqldb

コマンドラインで--spring.profiles.active=dev,hsqldbスイッチを使用して指定することも可能です。

22.1 アクティブなプロファイルを追加する

(興味がないのでパス)

22.2 プログラム・コードからプロファイルを指定する

アプリケーションの起動に先立ちSpringApplication.setAdditionalProfiles(…)を呼び出すことでアクティブなプロファイルをプログラム・コードから設定することが可能です。Springフレームワークの提供するConfigurableEnvironmentインターフェースによりプロファイルをアクティブ化することもまた可能です。

22.3 プロファイル固有のコンフィギュレーション・ファイル

(興味がないのでパス)

23. ロギング

Spring Bootはすべての内部的なロギングにCommons Loggingを使用していますが、基本的なログ実装はオープンな状態にしてあります。Java Util Logging、Log4JそしてLogbackのためにデフォルトの設定が提供されています。いずれのケースでもコンソール出力とファイル出力が行われます(ファイルは10MBごとにローテートされます)。

デフォルトでは、‘Starter POMs’を使用している場合、ロギングにはLogbackが使用されます。Java Util Logging、Commons Logging、Log4JあるいはSLF4Jを使用するライブラリはすべて正しく機能するよう適切なルーティング設定が含まれています。

Javaの世界には多くのロギング・フレームワークが存在します。しかし心配ご無用です。上述のフレームワークの一覧で混乱しそうに思われたとしても、一般的に言ってロギングに関する依存性を変更したりする必要はなく、Spring Bootはデフォルトの状態でうまくやってくれます。

23.1 ログ・フォーマット

(興味がないのでパス)

23.2 コンソール出力

(興味がないのでパス)

23.3 ファイル出力

(興味がないのでパス)

23.4 ログ・レベル

(興味がないのでパス)

23.5 独自のログ設定

          * * *

原典は"Spring Boot Reference Guide"(1.1.8.RELEASE版。2014/10/28取得)の"Part IV. Spring Boot features"です。続きはまた今度


Spring関連の訳出記事まとめ - M12i.