2

特定の環境で特定のプロパティをオーバーライドできるプロパティ設定が必要です。たとえば、dev のデフォルトの JDBC プロパティは次のとおりです。

  • db.driverClassName=com.mysql.jdbc.Driver
  • db.url=jdbc:mysql://localhost:3306/ourdb
  • データベースのユーザー名=ルート
  • デシベル。パスワード=

問題は、一部の開発者がデータベースに別のユーザー名/パスワードを使用したい、またはローカルでホストされていないデータベースを使用したいと考えていることです。同じことが、現在同様のローカルホスト、ゲスト/ゲスト設定を使用している rabbitMQ 構成にも当てはまります。開発者ごとにこの構成の特定の要素のプロパティをオーバーライドできると、ソフトウェアを構築するためのインフラストラクチャ/インストール要件の多くを、ローカル マシンから専用サーバーに移すことができます。

私が望むものを達成するために必要な構成に頭を包むための簡単なプロジェクトをセットアップしました。これまで、プロパティのロードと管理はいくつかのカスタムで行われていたため、これは春のプロパティ構成の世界への私の最初の進出です。コード。これが私のセットアップです:

class Main_PropertyTest {
    public static void main(String[] args) {
        String environment = System.getenv("APPLICATION_ENVIRONMENT"); // Environment, for example: "dev"
        String subEnvironment = System.getenv("APPLICATION_SUB_ENVIRONMENT"); // Developer name, for example: "joe.bloggs"
        System.setProperty("spring.profiles.active", environment);
        System.setProperty("spring.profiles.sub", subEnvironment);

        try(AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PropertyTestConfiguration.class)) {
            Main_PropertyTest main = context.getBean(Main_PropertyTest.class);
            main.printProperty();
        }
    }

    private final String property;

    public Main_PropertyTest(String property) {
        this.property = property;
    }

    public void printProperty() {
        System.out.println("And the property is: '" + property + "'.");
    }
}

そして私の設定:

@Configuration
public class PropertyTestConfiguration {
    @Bean
    public static PropertySourcesPlaceholderConfigurer primaryPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
        propertySourcesPlaceholderConfigurer.setLocation(new ClassPathResource(System.getProperty("spring.profiles.active") + ".main.properties"));
        return propertySourcesPlaceholderConfigurer;
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer secondaryPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
        propertySourcesPlaceholderConfigurer.setLocation(new ClassPathResource(System.getProperty("spring.profiles.sub") + ".main.properties"));
        propertySourcesPlaceholderConfigurer.setIgnoreResourceNotFound(true);
        propertySourcesPlaceholderConfigurer.setIgnoreResourceNotFound(true);
        propertySourcesPlaceholderConfigurer.setOrder(-1);
        return propertySourcesPlaceholderConfigurer;
    }

    @Bean
    public Main_PropertyTest main_PropertyTest(@Value("${main.property}") String property) {
        Main_PropertyTest main_PropertyTest = new Main_PropertyTest(property);
        return main_PropertyTest;
    }
}

完全を期すために、私の dev.main.properties と test.main.properties:

main.property=dev

main.property=test

主な問題は、不正な引数の例外が発生することです。私が知る限り、私が書いたものは、このメソッドに相当する javaconfig でなければなりません: http://taidevcouk.wordpress.com/2013/07/04/overriding-a-packaged-spring-application-properties-file-外部ファイル経由/ 残念ながら、次のエラーが発生します: java.lang.IllegalArgumentException: 文字列値 "${main.property}" のプレースホルダー 'main.property' を解決できませんでした。サブ環境がない場合にも注意する必要があることに注意してください。これは、私が始めたケースです (ただし、両方のファイルが存在する場合でも同じエラーが発生します)。2 番目の propertysourcesplaceholderconfigurer を設定する Bean を削除すると、すべて正常に動作します (つまり、dev.main.properties が読み込まれ、"And the property is: 'dev'." が出力されます)。

二次的な問題は、コードが見栄えがよくないことです。システムの各レイヤーは、これらのプロパティにアクセスできるように 2 つの PSPC のセットアップが必要になります。さらに、${spring.profiles.active} を PSPC.setLocation(); に渡すことができなかったため、System.getProperty() を手動で呼び出す必要があります。

注: @PropertySources({primaryproperties, secondaryProperties}) を試しましたが、secondaryProperties が存在しないため失敗します。@Autowired Environment 環境も試しました。そこからプロパティを取得しますが、セカンダリ PSPC により環境が自動配線されません...

この長い説明に続いて、私の質問は次のとおりです。

  • これは、この問題を解決する正しい方法ですか?
  • もしそうなら、私の設定の何が問題になっていますか?
  • 構成を簡素化するにはどうすればよいですか (もしあれば)。
  • 私の問題を解決する代替メカニズムはありますか?

お時間をいただきありがとうございます!:)

4

2 に答える 2

1

統合テストで既存のプロパティを上書きするという同様の問題がありました

私はこの解決策を思いつきました:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {
    SomeProdConfig.class,
    MyWebTest.TestConfig.class
})
@WebIntegrationTest
public class MyWebTest {


    @Configuration
    public static class TestConfig {

        @Inject
        private Environment env;


        @PostConstruct
        public void overwriteProperties() throws Exception {
            final Map<String,Object> systemProperties = ((ConfigurableEnvironment) env)
                .getSystemProperties();
            systemProperties.put("some.prop", "test.value");
        }
    }
于 2016-03-03T10:45:21.927 に答える