52

Beanを構築するため@Configurationのプロパティが必要なSpring3.1があります。fooプロパティはで定義されていますが、アプリケーションにアクティブなSpringプロファイルがある場合はdefaults.properties、のプロパティで上書きされる可能性があります。overrides.propertiesoverride

オーバーライドがないと、コードは次のようになり、機能します...

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

    @Autowired
    private Environment environment;

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

@PropertySourceclasspath:overrides.properties条件にをお願いし@Profile("overrides")ます。これをどのように達成できるかについて誰かが何か考えを持っていますか?私が検討したいくつかのオプションは重複しています@Configurationが、それはDRYまたはプログラムによる操作に違反しますが、呼び出しがどこに行くConfigurableEnvironmentのかわかりません。environment.getPropertySources.addFirst()

以下をXML構成に配置すると、プロパティを直接挿入した場合は機能しますが、メソッド@Valueを使用した場合は機能しません。EnvironmentgetRequiredProperty()

<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>

アップデート

今これを行おうとしている場合は、Spring BootのYAMLサポート、特に「プロパティの代わりにYAMLを使用する」セクションを確認してください。そこでのプロファイルサポートはこの質問を無意味にしますが、@PropertySourceまだサポートはありません。

4

7 に答える 7

53

オーバーライド@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");
        ...
    }
}
于 2013-01-05T00:55:20.013 に答える
10

できるよ:

  <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/>

複数のプロファイルに関するご質問にはお答えできませんが、そのような初期化子でそれらをアクティブ化し、プロファイルのアクティブ化中に適切な PropertySource 項目を登録できると思います。

于 2012-11-09T14:31:55.187 に答える
4

複数のプロファイルをサポートする必要がある場合は、次のようにすることができます。

@Configuration
public class Config {

    @Configuration
    @Profile("default")
    @PropertySource("classpath:application.properties")
    static class DefaultProperties {
    }

    @Configuration
    @Profile("!default")
    @PropertySource({"classpath:application.properties", "classpath:application-${spring.profiles.active}.properties"})
    static class NonDefaultProperties {
    }
}

そうすれば、プロファイルごとに静的構成クラスを定義する必要がなくなります。私を正しい方向に導いてくれたDavid Harknessに感謝します。

于 2019-09-02T12:21:03.717 に答える
3

注:この回答は、でプロパティファイルを使用するための代替ソリューションを提供します@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;
    }
}

サーブレットコンテキスト初期化子のアクティブなプロファイルに基づいてプロパティファイルを手動で構成することについて、これに固執することをまだ確信していません。私の考えでは、手動構成を行うことは単体テストには適していないだろうと思っていましたが、今はよくわかりません。私は、プロパティアクセサーのリストよりも、プロパティファイルを読み取る方が本当に好きです。

于 2013-01-05T00:13:45.643 に答える
3

あなたがエマーソンに提案した方法以外に、この Bean を注釈@Configuration付きの別のファイルで定義する方法は考えられません。@Profile

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

    @Autowired
    private Environment environment;

    @Bean
    public Bean bean() {
        //if..
    }
}
于 2012-10-02T14:39:06.963 に答える