『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); }
アプリケーションが起動すると下記のような出力を目にすることになるでしょう:
デフォルトでは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'を参照してください。
設定可能なオプションの完全なリストについてはSpringApplication
のJavadocを参照してください。
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フレームワーク内部で使用されているインターフェースで、実行中のアプリケーションの設定情報を保持している〕が親側でも子ども側でも使用されている必要があります。詳細についてはSpringApplicationBuilder
のJavadocを参照してください。
20.4 アプリケーション・イベントとリスナー
ContextRefreshedEvent
のような便利なSpringフレームワーク・イベントに加えて、SpringApplication
クラスはいくつかのアプリケーション・イベントを発生させます。いくつかのイベントはApplicationContext
が生成されるよりも前に生起されます。
イベント・リスナーはいくつかの方法で登録できますが、もっとも一般的な方法はSpringApplication.addListeners(…)
メソッドを使用する方法です。
アプリケーションが起動されると、アプリケーション・イベントは以下の順序で発生します:
- アプリケーションが起動されると
ApplicationStartedEvent
が発生します。これはリスナーの登録と初期化を除くいかなる処理よりも先んじて発生します。 ApplicationEnvironmentPreparedEvent
は起動したアプリケーションのコンテキストにおいて使用されるEnvironment
が確認されたあと、ただしコンテキストそのものが生成されるよりも前に発生します。ApplicationPreparedEvent
はリフレッシュ〔訳注:コンフィギュレーションにしたがってビーン=オブジェクトが初期化される?〕が開始される直前、ただし定義の読み込み自体は完了したあとに発生します。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
ビーンについてそれらのメソッドが呼び出される順序を指定できます。
21. 外部化されたコンフィギュレーション
Spring Bootは外部化されたコンフィギュレーションもサポートしています。これによって、同じアプリケーション・コードを異なる環境で動かすことが可能になります。形式としては、プロパティ・ファイル、YAMLファイル、環境変数、そしてコマンドライン引数が使用できます。プロパティ値は、@Value
アノテーションを使用して直接ビーンのフィールドに注入させることも、SpringのEnvironment
を通じてアクセスすることも、構造化されたオブジェクトにバインドさせることも可能です。
Spring Bootはプロパティ値の上書きを考慮して非常に限定された順序でPropertySource
をロードします。プロパティは以下の優先度で処理されます:
- コマンドライン引数
- Javaシステム・プロパティ(
System.getProperties()
) - OS環境変数
- java:comp/env由来のJNDI属性
random.*
系のプロパティを提供するRandomValuePropertySource
- jarパッケージ外部のアプリケーション・プロパティ(YAMLやプロファイル・ヴァリアントを含むapplication.properties)
- jarパッケージ内部のアプリケーション・プロパティ(YAMLやプロファイル・ヴァリアントを含むapplication.properties)
@Configuration
クラスの@PropertySource
アノテーション- デフォルト・プロパティ(
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
で、OPEN
とCLOSE
は何らかの文字〔訳注:ようするに丸括弧でもブラケットでも何でもよいらしい〕、そして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
に登録します:
- カレントディレクトリの/configサブディレクトリ
- カレントディレクトリ
- クラスパス内の/config配下
- クラスパスの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_path
は contextPath
にバインドされる)や、キャピタライズされた名前(例えばPORT
は port
にバインドされる)などがそうです。
@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"です。続きはまた今度。