LoginSignup
0
0

More than 1 year has passed since last update.

SpringBootでapplication.ymlやapplication-[プロファイル名].yml以外のファイル名のプロパティファイルを読みたい

Last updated at Posted at 2020-07-10

なかなかコレ!というサンプルが見つからなかったのでメモ。

やりたかったこと

マルチプロジェクトの構成で、共通の部品を集めたプロジェクト側にもプロパティファイルを置きたかったが、application.yml だと利用側のプロパティファイルと名前がバッティングするため別名にする必要があった。

  • SpringBoot に application-common.yml のような名前の yaml のプロパティファイルを読み込ませる
  • その際、application-common-test.yml のようにプロファイル名をくっつけたファイルも読み込ませる
  • 読み込んだプロパティは Configuration クラスにマッピングする

実現方法

ポイント

  • Configuration クラスで @PropertySource を使用して読み込むプロパティファイルを指定する
  • @PropertySource は yaml ファイルの読み込みに対応していないので読み込み用のクラスを作成して読み込めるようにする

ソースコード

完全なソースコードはこちら

Configuration クラス

@PropertySourcevalue で ファイル名を、factory で Yaml 読み込み用のクラスを指定する。

FooConfig.java
@Configuration
@ConfigurationProperties(prefix = "foo")
@Component
@PropertySource(value = {"classpath:/foo-config.yml",
    "classpath:/foo-config-${spring.profiles.active}.yml"},
    factory = YamlPropertySourceFactory.class)
@Data
public class FooConfig {

    private BarConfig bar;
    private BazConfig baz;

    @Data
    public static class BarConfig {
        private String setting1;
    }

    @Data
    public static class BazConfig {
        private String setting1;
        private String setting2;
    }
}

Factory クラス

どこかから拝借したソース。
Spring のYamlPropertiesFactoryBeanを使用して読み込んだ Yaml を Properties に変換し、PropertySource にして返しているよう。

YamlPropertySourceFactory.java
public class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource)
        throws IOException {
        Properties propertiesFromYaml = loadYamlIntoProperties(resource);
        String sourceName = name != null ? name : resource.getResource().getFilename();
        return new PropertiesPropertySource(sourceName, propertiesFromYaml);
    }

    private static Properties loadYamlIntoProperties(EncodedResource resource)
        throws FileNotFoundException {
        try {
            YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
            factory.setResources(resource.getResource());
            factory.afterPropertiesSet();
            return factory.getObject();
        } catch (IllegalStateException e) {
            Throwable cause = e.getCause();
            if (cause instanceof FileNotFoundException) {
                throw (FileNotFoundException) e.getCause();
            }
            throw e;
        }
    }
}

動作確認

SpringPropertySourceTest.java
@SpringBootTest
@ActiveProfiles("test")
public class SpringPropertySourceTest {

    @Autowired
    FooConfig fooConfig;

    @Test
    public void test() {
        assertThat(fooConfig.getBar().getSetting1()).isEqualTo("barbar1");
        assertThat(fooConfig.getBaz().getSetting2()).isEqualTo("bazbaz2");

    }
}

おまけ

SpringBoot2.3.0 以降だと@PropertySource${spring.profiles.active} を解決できずにエラーが出ます。別記事に書いておきました。(これのせいでめっちゃ時間食った・・・)

SpringBoot2.3.0 以降で@PropertySource の value に使用しているプレースホルダの解決に失敗する

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0