2012-10-02 6 views
32

私はBeanを構築するために、プロパティーfooを必要とするSpring 3.1 @Configurationを持っています。このプロパティはdefaults.propertiesで定義されていますが、アプリケーションにアクティブなoverrideスプリングプロファイルがある場合は、overrides.propertiesのプロパティで上書きされる可能性があります。@PropertySourcesはSpringプロファイルによって選択できますか?

オーバーライドしないと、コードは次のようになり、仕事だろう...

@Configuration 
@PropertySource("classpath:defaults.properties") 
public class MyConfiguration { 

    @Autowired 
    private Environment environment; 

    @Bean 
    public Bean bean() { 
     ... 
     // this.environment.getRequiredProperty("foo"); 
     ... 
    } 
} 

私は@Profile("overrides")@PropertySourceclasspath:overrides.propertiesのための偶発をしたいと思います。誰にどのようにこれを達成できるかについてのアイデアはありますか?私が考えてきたいくつかのオプションは、@Configurationという重複ですが、DRYまたはプログラムによるConfigurableEnvironmentの操作に違反しますが、environment.getPropertySources.addFirst()の呼び出しがどこに行くのかはわかりません。

プロパティを直接@Valueに挿入すると、次のように配置されますが、Environmentとメソッドを使用した場合は無効になります。

<context:property-placeholder ignore-unresolvable="true" location="classpath:defaults.properties"/> 

<beans profile="overrides"> 
    <context:property-placeholder ignore-unresolvable="true" order="0" 
            location="classpath:overrides.properties"/> 
</beans> 

更新

あなたは、今、これを行う春ブーツのYAML support、特に「を使用YAMLの代わりのプロパティ」セクションをチェックアウトしようとしている場合。そこでのプロファイルのサポートはこの疑問を解決するでしょうが、まだ@PropertySourceのサポートはありません。

答えて

39

オーバーライド@PropertySourceを静的内部クラスに追加します。残念なことに、すべてのプロパティーソースを一緒に指定する必要があります。つまり、「オーバーライド」の代わりに「デフォルト」プロファイルを作成することです。

@Configuration 
public class MyConfiguration 
{ 
    @Configuration 
    @Profile("default") 
    @PropertySource("classpath:defaults.properties") 
    static class Defaults 
    { } 

    @Configuration 
    @Profile("override") 
    @PropertySource({"classpath:defaults.properties", "classpath:overrides.properties"}) 
    static class Overrides 
    { 
     // nothing needed here if you are only overriding property values 
    } 

    @Autowired 
    private Environment environment; 

    @Bean 
    public Bean bean() { 
     ... 
     // this.environment.getRequiredProperty("foo"); 
     ... 
    } 
} 
+2

理由を理解できませんこの回答には非常に多くのアップフォースがあります。プロファイル名をハードコーディングするのは、プロファイルのポイントに反します。 'spring.profiles.active'パラメータでプロファイルを指定するのと同じような方法はありませんか? – jjoller

2

私はあなたが@Profile注釈を持つ別の@ConfigurationのファイルにこのBeanを定義することであるエマーソン、示唆されているものよりも、他の方法を考えることはできません:あなたが行うことができます

@Configuration 
@Profile("override") 
@PropertySource("classpath:override.properties") 
public class OverriddenConfig { 

    @Autowired 
    private Environment environment; 

    @Bean 
    public Bean bean() { 
     //if.. 
    } 
} 
7

<context:property-placeholder location="classpath:${spring.profiles.active}.properties" /> 

編集:さらに高度なものが必要な場合は、アプリケーションの起動時にPropertySourcesを登録することができます。

web.xmlの

<context-param> 
    <param-name>contextInitializerClasses</param-name> 
    <param-value>com.xxx.core.spring.properties.PropertySourcesApplicationContextInitializer</param-value> 
    </context-param> 

作成したファイル:

public class PropertySourcesApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { 

    private static final Logger LOGGER = LoggerFactory.getLogger(PropertySourcesApplicationContextInitializer.class); 

    @Override 
    public void initialize(ConfigurableApplicationContext applicationContext) { 
    LOGGER.info("Adding some additional property sources"); 
    String[] profiles = applicationContext.getEnvironment().getActiveProfiles() 
    // ... Add property sources according to selected spring profile 
    // (note there already are some property sources registered, system properties etc) 
    applicationContext.getEnvironment().getPropertySources().addLast(myPropertySource); 
    } 

} 

あなたがそれをやったらあなたは自分のコンテキストで追加する必要があります。

<context:property-placeholder/> 

私ができます」本当に複数のプロファイルについてのあなたの質問に答えるが、私はあなたがそのようなイニシャライザでそれらをアクティブにすると思います、あなたはappropを登録することができますプロファイルのアクティブ化中にPropertySource項目をリレートします。

+1

プロファイルは1つだけアクティブであると仮定していませんか? –

+2

'applicationContext.getEnvironment()。getActiveProfiles()' –

+0

を使用して、アクティブなプロファイルの解析済みリストに配列としてアクセスできます。その時私は複数のプロファイルを渡すことができなかった;) –

2

注:この回答は、@PropertySourceのプロパティファイルを使用する代わりの方法を示しています。反復コードを避けながら、それぞれが上書きする可能性のある複数のプロパティファイルを処理しようとするのはあまりにも面倒だったので、私はこのルートを使いました。

それぞれの関連プロパティセットに対してPOJOインターフェイスを作成して、名前とタイプを定義します。

public interface DataSourceProperties 
{ 
    String driverClassName(); 
    String url(); 
    String user(); 
    String password(); 
} 

デフォルト値を返すように実装します。

public class DefaultDataSourceProperties implements DataSourceProperties 
{ 
    public String driverClassName() { return "com.mysql.jdbc.Driver"; } 
    ... 
} 

各プロファイル(開発、生産など)にサブクラス化し、デフォルトと異なる値を上書きします。これには相互に排他的なプロファイルが必要ですが、「上書き」の代わりに「デフォルト」を簡単に追加できます。

@Profile("production") 
@Configuration 
public class ProductionDataSourceProperties extends DefaultDataSourceProperties 
{ 
    // nothing to override as defaults are for production 
} 

@Profile("development") 
@Configuration 
public class DevelopmentDataSourceProperties extends DefaultDataSourceProperties 
{ 
    public String user() { return "dev"; } 
    public String password() { return "dev"; } 
} 

最後に、プロパティ設定を必要な他の設定に自動配線します。ここでの利点は、@Bean作成コードを繰り返さないことです。

私はまだ私は手動でサーブレットコンテキスト初期化中にアクティブなプロファイルに基づいてプロパティファイルを設定する上で、これに固執するだろうと確信していないです
@Configuration 
public class DataSourceConfig 
{ 
    @Autowired 
    private DataSourceProperties properties; 

    @Bean 
    public DataSource dataSource() { 
     BoneCPDataSource source = new BoneCPDataSource(); 
     source.setJdbcUrl(properties.url()); 
     ... 
     return source; 
    } 
} 

。私の考えでは、手動で設定することは単体テストのようなものではないでしょうが、今はあまりよく分かりません。私は本当にプロパティのアクセサーのリストにプロパティファイルを読むことを好む。

+0

プロパティと '@ PropertySource'の主な特徴は、環境変数やアプリケーションスイッチなど、さまざまな方法でそれを上書きできることです。 – Raniz

関連する問題