1. 概要

このチュートリアルでは、Java構成および@PropertySource。を介してSpringでプロパティを設定および使用する方法を示します。

Spring Bootでプロパティがどのように機能するかも確認します。

2. 注釈を介してプロパティファイルを登録する

Spring 3.1では、プロパティソースを環境に追加するための便利なメカニズムとして、新しい@PropertySourceアノテーションも導入されています。

このアノテーションは、@Configurationアノテーションと組み合わせて使用できます。

@Configuration
@PropertySource("classpath:foo.properties")
public class PropertiesWithJavaConfig {
    //...
}

新しいプロパティファイルを登録するもう1つの非常に便利な方法は、プレースホルダーを使用することです。これにより、実行時に適切なファイルを動的に選択できます

@PropertySource({ 
  "classpath:persistence-${envTarget:mysql}.properties"
})
...

2.1. 複数のプロパティの場所を定義する

@PropertySource アノテーションは、Java8の規則に従って繰り返し可能です。 したがって、Java 8以降を使用している場合は、このアノテーションを使用して複数のプロパティの場所を定義できます。

@PropertySource("classpath:foo.properties")
@PropertySource("classpath:bar.properties")
public class PropertiesWithJavaConfig {
    //...
}

もちろん、 @PropertySourcesアノテーションを使用して、@ PropertySourceの配列を指定することもできます。これは、Java 8以降だけでなく、サポートされているすべてのJavaバージョンで機能します。

@PropertySources({
    @PropertySource("classpath:foo.properties"),
    @PropertySource("classpath:bar.properties")
})
public class PropertiesWithJavaConfig {
    //...
}

いずれの場合も、プロパティ名が衝突した場合は、最後に読み取られたソースが優先されることに注意してください。

3. プロパティの使用/挿入

@Valueアノテーションを使用したプロパティの挿入は簡単です。

@Value( "${jdbc.url}" )
private String jdbcUrl;

プロパティのデフォルト値を指定することもできます。

@Value( "${jdbc.url:aDefaultUrl}" )
private String jdbcUrl;

Spring3.1で追加された新しいPropertySourcesPlaceholderConfigurerは、Bean定義プロパティ値および@Valueアノテーション内の${…}プレースホルダーを解決します。

最後に、EnvironmentAPIを使用してプロパティの値を取得できます

@Autowired
private Environment env;
...
dataSource.setUrl(env.getProperty("jdbc.url"));

4. スプリングブートのプロパティ

プロパティのより高度な構成オプションに入る前に、Spring Bootでの新しいプロパティのサポートを見てみましょう。

一般的に言えば、この新しいサポートは、標準のSpring と比較して構成が少なくて済みます。これは、もちろんBootの主な目標の1つです。

4.1. application.properties:デフォルトのプロパティファイル

Bootは、設定より規約の一般的な規則をプロパティファイルに適用します。 これは、単にapplication.propertiesファイルをsrc / main / resourcesディレクトリに置くことができ、それが自動検出されることを意味します。 次に、ロードされたプロパティを通常どおりに挿入できます。

したがって、このデフォルトファイルを使用することで、 PropertySource を明示的に登録したり、プロパティファイルへのパスを指定したりする必要はありません。

必要に応じて、環境プロパティを使用して、実行時に別のファイルを構成することもできます。

java -jar app.jar --spring.config.location=classpath:/another-location.properties

Spring Boot 2.3 以降、構成ファイルのワイルドカードの場所を指定することもできます。

たとえば、spring.config.locationプロパティをconfig/ */に設定できます。

java -jar app.jar --spring.config.location=config/*/

このようにして、Spring Bootは、jarファイルの外部にある config / */ディレクトリパターンに一致する構成ファイルを探します。 これは、構成プロパティのソースが複数ある場合に便利です。

バージョン2.4.0以降、 Spring Bootはマルチドキュメントプロパティファイルの使用をサポートします。これは、YAMLが設計上するのと同様にです。

baeldung.customProperty=defaultValue
#---
baeldung.customProperty=overriddenValue

プロパティファイルの場合、3つのダッシュ表記の前にコメント文字()が付いていることに注意してください。

4.2. 環境固有のプロパティファイル

さまざまな環境をターゲットにする必要がある場合は、Bootにそのための組み込みメカニズムがあります。

src / main /resourcesディレクトリにapplication-environment.propertiesファイルを定義し、同じ環境名でSpringプロファイルを設定するだけです。

たとえば、「ステージング」環境を定義する場合、 staging プロファイルを定義してから、application-staging.propertiesを定義する必要があります。

このenvファイルがロードされ、がデフォルトのプロパティファイルよりも優先されます。デフォルトのファイルが引き続きロードされることに注意してください。プロパティの衝突が発生した場合、環境固有のプロパティファイルが優先されます。 。

4.3. テスト固有のプロパティファイル

また、アプリケーションのテスト中に、異なるプロパティ値を使用する必要がある場合もあります。

Spring Bootは、テスト実行中にsrc / test /resourcesディレクトリを調べることでこれを処理します。 繰り返しになりますが、デフォルトのプロパティは通常どおり注入可能ですが、衝突が発生した場合はこれらによってオーバーライドされます。

4.4. @TestPropertySourceアノテーション

テストプロパティをよりきめ細かく制御する必要がある場合は、@TestPropertySourceアノテーションを使用できます。

これにより、デフォルトのプロパティソースよりも優先して、特定のテストコンテキストのテストプロパティを設定できます。

@RunWith(SpringRunner.class)
@TestPropertySource("/foo.properties")
public class FilePropertyInjectionUnitTest {

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

    @Test
    public void whenFilePropertyProvided_thenProperlyInjected() {
        assertThat(foo).isEqualTo("bar");
    }
}

ファイルを使用したくない場合は、名前と値を直接指定できます。

@RunWith(SpringRunner.class)
@TestPropertySource(properties = {"foo=bar"})
public class PropertyInjectionUnitTest {

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

    @Test
    public void whenPropertyProvided_thenProperlyInjected() {
        assertThat(foo).isEqualTo("bar");
    }
}

@SpringBootTest アノテーションのプロパティ引数を使用して、同様の効果を実現することもできます。

@RunWith(SpringRunner.class)
@SpringBootTest(
  properties = {"foo=bar"}, classes = SpringBootPropertiesTestApplication.class)
public class SpringBootPropertyInjectionIntegrationTest {

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

    @Test
    public void whenSpringBootPropertyProvided_thenProperlyInjected() {
        assertThat(foo).isEqualTo("bar");
    }
}

4.5. 階層プロパティ

グループ化されたプロパティがある場合は、 @ConfigurationProperties アノテーションを使用して、これらのプロパティ階層をJavaオブジェクトグラフにマップできます。

データベース接続の構成に使用されるいくつかのプロパティを見てみましょう。

database.url=jdbc:postgresql:/localhost:5432/instance
database.username=foo
database.password=bar

次に、注釈を使用してそれらをデータベースオブジェクトにマップしましょう。

@ConfigurationProperties(prefix = "database")
public class Database {
    String url;
    String username;
    String password;

    // standard getters and setters
}

Spring Bootは、設定より規約を再度適用し、プロパティ名とそれに対応するフィールドを自動的にマッピングします。 提供する必要があるのは、プロパティのプレフィックスだけです。

構成プロパティをさらに詳しく知りたい場合は、詳細な記事を参照してください。

4.6. 代替:YAMLファイル

SpringはYAMLファイルもサポートしています。

テスト固有、環境固有、およびデフォルトのプロパティファイルには、すべて同じ命名規則が適用されます。 唯一の違いは、ファイル拡張子と、クラスパス上にあるSnakeYAMLライブラリへの依存関係です。

YAMLは、階層プロパティストレージに特に適しています。 次のプロパティファイル:

database.url=jdbc:postgresql:/localhost:5432/instance
database.username=foo
database.password=bar
secret: foo

次のYAMLファイルと同義です。

database:
  url: jdbc:postgresql:/localhost:5432/instance
  username: foo
  password: bar
secret: foo

YAMLファイルは@PropertySourceアノテーションをサポートしていないため、このアノテーションを使用する必要がある場合は、プロパティファイルの使用に制限されることにも言及する価値があります。

もう1つの注目すべき点は、バージョン2.4.0で、SpringBootがマルチドキュメントYAMLファイルからプロパティをロードする方法を変更したことです。 以前は、それらが追加された順序は、プロファイルのアクティブ化の順序に基づいていました。 ただし、新しいバージョンでは、フレームワークは.propertiesファイルについて前に示したのと同じ順序付け規則に従います。 ファイルの下位に宣言されたプロパティは、上位のプロパティを上書きするだけです。

さらに、このバージョンでは、プロファイルはプロファイル固有のドキュメントからアクティブ化できなくなり、結果がより明確で予測可能になります。

4.7. 追加の構成ファイルのインポート

バージョン2.4.0より前では、Spring Bootは、spring.config.locationおよびspring.config.additional-locationプロパティを使用して追加の構成ファイルを含めることを許可していましたが、特定の制限がありました。 たとえば、プロセスの早い段階で使用されたため、アプリケーションを開始する前に(環境またはシステムのプロパティとして、またはコマンドライン引数を使用して)定義する必要がありました。

上記のバージョンでは、 application.propertiesまたはapplication.ymlファイル内のspring.config.importプロパティを使用して、追加のファイルを簡単に含めることができます。このプロパティは、いくつかの興味深い機能をサポートしています。

  • 複数のファイルまたはディレクトリを追加する
  • ファイルは、クラスパスまたは外部ディレクトリからロードできます。
  • ファイルが見つからない場合、またはオプションのファイルである場合に起動プロセスが失敗するかどうかを示します
  • 拡張子のないファイルのインポート

有効な例を見てみましょう。

spring.config.import=classpath:additional-application.properties,
  classpath:additional-application[.yml],
  optional:file:./external.properties,
  classpath:additional-application-properties/

注:ここでは、わかりやすくするために改行を使用してこのプロパティをフォーマットしました。

Springは、インポートをインポート宣言のすぐ下に挿入された新しいドキュメントとして扱います。

4.8. コマンドライン引数からのプロパティ

ファイルを使用する以外に、コマンドラインでプロパティを直接渡すことができます。

java -jar app.jar --property="value"

これは、 -jar コマンドの後ではなく、前に提供されるシステムプロパティを介して行うこともできます。

java -Dproperty.name="value" -jar app.jar

4.9. 環境変数からのプロパティ

Spring Bootは環境変数も検出し、それらをプロパティとして扱います。

export name=value
java -jar app.jar

4.10. プロパティ値のランダム化

決定論的なプロパティ値が必要ない場合は、RandomValuePropertySourceを使用してプロパティの値をランダム化できます。

random.number=${random.int}
random.long=${random.long}
random.uuid=${random.uuid}

4.11. 追加のタイプのプロパティソース

Spring Bootは、多数のプロパティソースをサポートし、適切なオーバーライドを可能にするためによく考えられた順序を実装します。 公式ドキュメントを参照する価値があります。これは、この記事の範囲を超えています。

5. Raw Beansを使用した構成— PropertySourcesPlaceholderConfigurer

プロパティをSpringに取り込む便利な方法に加えて、プロパティ構成Beanを手動で定義および登録することもできます。

PropertySourcesPlaceholderConfigurer を使用すると、構成を完全に制御できますが、より冗長で、ほとんどの場合、不要であるという欠点があります。

Java構成を使用してこのbeanを定義する方法を見てみましょう。

@Bean
public static PropertySourcesPlaceholderConfigurer properties(){
    PropertySourcesPlaceholderConfigurer pspc
      = new PropertySourcesPlaceholderConfigurer();
    Resource[] resources = new ClassPathResource[ ]
      { new ClassPathResource( "foo.properties" ) };
    pspc.setLocations( resources );
    pspc.setIgnoreUnresolvablePlaceholders( true );
    return pspc;
}

6. 親子コンテキストのプロパティ

この質問は何度も出てきます。Webアプリケーションに親と子のコンテキストがあるとどうなりますか? 親コンテキストには、いくつかの共通のコア機能とBeanがあり、次に1つ(または複数)の子コンテキストがあり、サーブレット固有のBeanが含まれている場合があります。

その場合、プロパティファイルを定義し、それらをこれらのコンテキストに含めるための最良の方法は何ですか? そして、これらのプロパティをSpringから最適に取得する方法は?

簡単な内訳を示します。

ファイルが親コンテキストで定義されている場合:

  • @Value 子コンテキストで機能します:はい
  • @Value 親コンテキストで機能します:はい
  • 子コンテキストenvironment.getProperty:はい
  • 親コンテキストenvironment.getProperty:はい

ファイルが子コンテキスト定義されている場合:

  • @Value 子コンテキストで機能します:はい
  • @Value 親コンテキストで機能します:いいえ
  • 子コンテキストenvironment.getProperty:はい
  • 親コンテキストenvironment.getProperty:いいえ

7. 結論

この記事では、Springでプロパティとプロパティファイルを操作するいくつかの例を示しました。

いつものように、記事を裏付けるコード全体は、GitHub利用できます。