👻

Re:ゼロから始めるSpring Boot #3 アプリケーションプロパティファイル

2023/12/04に公開

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

Spring Bootにおける application.properties ファイルは、アプリケーションの設定情報を外部化し、様々な構成オプションを提供するための標準的なプロパティ ファイルです。以下は、application.properties ファイルの主な特徴と使い方についての簡単な説明です。

  1. アプリケーションの構成: application.properties ファイルは、Spring Bootアプリケーションの様々な構成オプションを指定するために使用されます。これには、データベースの接続設定、サーバーポート、ログの設定などが含まれます。
  2. キーと値の形式: ファイル内の各行は、key=value の形式で記述されます。たとえば、データベースの接続設定を指定する場合、spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase のような形式です。
  3. プロパティのオーバーライド: application.properties ファイルは、複数の方法でオーバーライドできます。たとえば、同じプロパティがコマンドライン引数や環境変数で指定された場合、それらが優先されます。
  4. プロファイルごとの設定: プロファイルごとに異なる設定をしたい場合、application-{profile}.properties ファイルを作成し、{profile} 部分に対応するプロファイル名を指定します。たとえば、application-dev.properties は dev プロファイル用の設定を提供します。
  5. YAML形式の代替: application.properties ファイルの代わりに、同じ設定をYAML形式で記述することも可能です。application.yml または application.yaml というファイル名で保存します。

Spring Bootの共通アプリケーションプロパティ:
https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#appendix.application-properties

アプリケーションプロパティを触ってみよう

内蔵Tomcatのポートとアプリのコンテキストパスを変更する例:

実行結果

コンソールログでport番号とcontext pathが変わったことを確認できた。

yml/yaml形式

yml形式はMarkDown形式なのでapplication.propertiesより可読性が高い。
application.propertiesapplication.ymlファイルは同時に存在する場合は、application.propertiesが利用される。そのためapplication.propertiesを削除する必要がある。

実行結果

application.ymlファイルにあるプロパティが利用されていることがわかる。

プロパティの参照

@Valueを用いるプロパティの参照

実装方法:プロパティを参照するクラスに@Value(${key}もしくは@Value(${key:default}を記載する。default値はプロパティファイルに指定のプロパティが存在しない場合に適用される。

@Valueの実装例

application.yml

app:
  name: ReZeroSpringBoot
  owner: willyang
  port: 9999

Service
\src\main\java\com\rezerosb\rezerosb03_config\pkg1\SomeService.java

@Service
public class SomeService {
    @Value("${app.name}")
    private String name;
    // @Value("${app.owner}")
    private String owner;
    @Value("${app.port:8008}")
    private Integer port;
    public void printValue(){
        StringJoiner joiner = new StringJoiner(";");
        joiner.add(name).add(owner).add(String.valueOf(port));
        String result = joiner.toString();
        System.out.println("result="+result);
    }
}

テストコード
\src\test\java\com\rezerosb\rezerosb03_config\RezeroSb03ConfigApplicationTests.java

@SpringBootTest
class RezeroSb03ConfigApplicationTests {

    @Autowired
    private SomeService someService;

    @Test
    void test01() {
        someService.printValue();
    }
}

実行結果

Environment

Environmentは、アプリケーションの構成情報やプロパティを取得するためのインタフェースです。EnvironmentはSpringのApplicationContextに統合されており、アプリケーションがどの環境で実行されているかや、どのプロファイルがアクティブであるかなどの情報を提供します。

Environmentの主な特徴と用途:

  1. プロパティの取得: Environmentを使用して、アプリケーションのプロパティを取得できます。これには、application.propertiesやapplication.ymlなどの設定ファイルで指定されたプロパティが含まれます。
  2. プロファイルの管理: Environmentはアクティブなプロファイルやデフォルトのプロファイルなどの情報を提供します。プロファイルは異なる設定を使いたい場合に有用であり、環境ごとに異なる設定を簡単に切り替えることができます。
  3. コマンドライン引数の処理: 実行時のコマンドライン引数から値を取得する機能があります。例えば、--server.port=8080のような引数を指定することで、ポート番号を変更できます。
  4. プロパティの優先順位: Environmentはプロパティの優先順位を管理します。例えば、同じプロパティが複数の場所で指定された場合、どの値が採用されるかを制御します。通常、環境変数やコマンドライン引数がより高い優先順位を持ちます。

Environmentは主にConfigurableEnvironment インタフェースを通じて利用され、StandardEnvironmentがその実装の1つです。Spring Bootでは、この仕組みを活用してアプリケーションの柔軟な構成管理を実現可能。

Environmentの利用例

Service
import org.springframework.core.env.Environment が必要。

package com.rezerosb.rezerosb03_config.pkg2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

@Service
public class ReadConfig {
    @Autowired
    private Environment environment;

    public void print() {
        String name = environment.getProperty("app.name");
        if (environment.containsProperty("app.owner")) {
            System.out.println("app.owner =" + environment.getProperty("app.owner"));
        }
        Integer port = environment.getProperty("app.port", Integer.class, 9009);

        String str = String.format("name=%s, port=%d", name, port);
        System.out.println("str = " + str);
    }
}

テストコード

    @Autowired
    private ReadConfig readConfig;

    @Test
    void test02() {
        readConfig.print();
    }

実行結果

複数のプロパティファイルの扱い方

resourcesは以下にプロパティファイルを作成してapplication.ymlにプロパティファイルをインポートすることができる。

具体例

└───resources
    │   application.yml
    │
    └───config
            db.yml
            redis.yml

application.yml

# プロパティファイルをインポートする
spring:
  config:
    import: conf/db.yml,conf/redis.yml

複数環境に対応するプロパティファイル

環境(プロファイル)ごとに異なる設定をしたい場合、application-{profile}.properties ファイルを作成し、{profile} 部分に対応するプロファイル名を指定します。たとえば、application-dev.properties 、application-qa.properties は 開発環境はdev、QA環境はqaプロファイル用の設定を提供できる。

実装してみよう

application.yml

spring:
  config:
    import: config/db.yml,config/redis.yml
  profiles:
    active: dev

application-dev.yml

myapp:
  memo: This is dev.
spring:
  config:
    activate:
      on-profile: dev

Service

@Service
public class MultiEnvService {

    @Value("${myapp.memo}")
    private String memo;

    public void print(){
        System.out.println(memo);
    }
}

Test

    @Autowired
    private MultiEnvService service;

    @Test
    void test03(){
        service.print();
    }

実行結果

Beanの利用

これまでのやり方は@Valueを利用して単一の属性をバインドしますが、複数の属性がある場合には不便です。Spring Bootでは、Beanのプロパティに複数の構成項目をバインドし、強力な型のBeanを提供する別の属性の方法が提供されています。Beanは構成データにアクセスできます。

基本原則:標準のJava Beanはパラメータのないコンストラクタと、プロパティのアクセサを持っています。@ConfigurationPropertiesアノテーションと一緒に使用します。Beanのstaticプロパティはサポートされていません。

Spring Bootのオートコンフィグレーションでは、@Beanと@ConfigurationPropertiesをバインドすることが頻繁に行われ、フレームワークのカスタムパラメータを提供します。プロジェクトで使用するデータが可変の場合、ymlまたはpropertiesファイルで提供することが推奨されます。プロジェクトコードは非常に柔軟性があります。
@ConfigurationPropertiesは複数の単純な型のプロパティを構成でき、同時にMap、List、配列型もサポートしています。プロパティのバリデーションも可能。

Beanの利用例

@Configuration
@ConfigurationProperties(prefix = "app")
public class AppBean {
    private String name;
    private String owner;
    private Integer port;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        this.owner = owner;
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    @Override
    public String toString() {
        return "AppBean{" +
                "name='" + name + '\'' +
                ", owner='" + owner + '\'' +
                ", port=" + port +
                '}';
    }
}

Test

    @Autowired
    private AppBean appBean;

    @Test
    void test04(){
        System.out.println("appBean = " + appBean.toString());
    }

実行結果

appBean = AppBean{name='RezeroSB03', owner='Willyang', port=9999}

ファイル一覧

まとめ

Spring Bootのアプリケーションプロパティは、デフォルトでapplication.propertiesに記載する。application.propertiesより、yaml形式ファイルのほうは可読性が高いため、application.ymlを利用すべき。application.ymlファイルに別のプロパティファイルをインポートできる。application-{profile}.yml のようにプロファイルごとに異なる設定もできる。

Beanのバインド:複数のプロパティに使用されます。
アノテーション:@ConfigurationProperties
位置:
1)クラスの上にあり、ソースコードが必要です
2)メソッドの上にあり、サードパーティのオブジェクトを使用します。@Beanアノテーションと一緒に使用します。
データの出所:applicationファイル(propertiesまたはyml)
データの出所を指定:@PropertySource(value = "xxx.properties")

注意:1)クラスにはパラメータのないコンストラクタが必要です
2)属性にはsetXXXメソッドが必要です
3)static属性は無効です
4)Beanのコンストラクタを使用してもオブジェクトを作成でき、setメソッドは必要ありません

@ConfigurationPropertiesの使用には他のアノテーションが必要です:
1)@Configuration
2)@EnableConfigurationProperties
3)@ConfigurationPropertiesScan

Discussion