복붙노트

[SPRING] @PropertySources는 Spring 프로필에 의해 선택 될 수 있습니까?

SPRING

@PropertySources는 Spring 프로필에 의해 선택 될 수 있습니까?

bean을 만들기 위해 foo 속성이 필요한 Spring 3.1 @Configuration이 있습니다. 이 속성은 defaults.properties에 정의되어 있지만 응용 프로그램에 활성 override Spring 프로필이있는 경우 overrides.properties의 속성에 의해 무시 될 수 있습니다.

재정의하지 않으면 코드가 다음과 같이 보이고 작동합니다.

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

    @Autowired
    private Environment environment;

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

나는 classpath를 위해 @PropertySource를 원한다 : @Profile ( "overrides")을 조건으로하는 overrides.properties. 이것이 달성 될 수있는 방법에 대한 아이디어가있는 사람이 있습니까? 일부 옵션은 중복 된 @Configuration으로 간주되지만 DRY 또는 ConfigurableEnvironment의 프로그래밍 방식 조작에 위배됩니다. 그러나 environment.getPropertySources.addFirst () 호출이 어디로 갈지는 확실하지 않습니다.

@Value를 사용하여 속성을 직접 주입하면 XML 구성에 다음을 배치 할 수 있지만 Environment 및 getRequiredProperty () 메서드를 사용하는 경우에는 사용할 수 없습니다.

<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 지원, 특히 '속성 대신 YAML 사용'섹션을 확인하십시오. 그곳에서의 프로파일 지원은이 질문을하게 만들지 만 아직 @PropertySource 지원은 없습니다.

해결법

  1. ==============================

    1.재정의 된 @PropertySource를 정적 내부 클래스에 추가하십시오. 불행히도 "대체"의 대안으로 "기본"프로파일을 만드는 것을 의미하는 모든 속성 소스를 함께 지정해야합니다.

    재정의 된 @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. ==============================

    2.넌 할 수있어:

    넌 할 수있어:

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

    편집 : 좀 더 고급 기능이 필요한 경우 응용 프로그램 시작시 PropertySources를 등록 할 수 있습니다.

    을 포함한다.

      <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 항목을 등록 할 수있을 것 같아요.

  3. ==============================

    3.@Profile 주석을 사용하여 별도의 @Configuration 파일에이 빈을 정의하는 Emerson을 제안한 것 외에는 다른 방식을 생각할 수 없습니다.

    @Profile 주석을 사용하여 별도의 @Configuration 파일에이 빈을 정의하는 Emerson을 제안한 것 외에는 다른 방식을 생각할 수 없습니다.

    @Configuration
    @Profile("override")
    @PropertySource("classpath:override.properties")
    public class OverriddenConfig {
    
        @Autowired
        private Environment environment;
    
        @Bean
        public Bean bean() {
            //if..
        }
    }
    
  4. ==============================

    4.참고 :이 대답은 @PropertySource로 특성 파일을 사용하는 다른 해결책을 제공합니다. 반복적 인 코드를 피하면서 각 속성을 재정의 할 수있는 여러 속성 파일로 작업하기가 너무 번거롭기 때문에이 경로를 따라갔습니다.

    참고 :이 대답은 @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;
        }
    }
    

    나는 아직도 서블릿 컨텍스트 이니셜 라이저의 활성 프로파일을 기반으로 속성 파일을 수동으로 구성하여이 작업을 계속 수행 할 것이라고 확신하지 못합니다. 내 생각에 수동 구성을하면 단위 테스트에 적합하지 않지만 지금은 확실하지 않습니다. 필자는 속성 접근 자 목록에 속성 파일을 읽는 것을 선호합니다.

  5. from https://stackoverflow.com/questions/12691812/can-propertysources-be-chosen-by-spring-profile by cc-by-sa and MIT license