복붙노트

[SPRING] YAML을 사용하여 Spring @PropertySource

SPRING

YAML을 사용하여 Spring @PropertySource

Spring Boot를 사용하면 application.properties 파일을 YAML 파일로 대체 할 수 있습니다. 그러나 나는 시험에 걸림돌을 치는 것 같다. TestConfiguration (간단한 Java 구성)에 주석을 달면 속성 파일이 필요합니다.

예를 들면 다음과 같이 작동하지 않습니다. @PropertySource (value = "classpath : application-test.yml")

YAML 파일에 다음과 같이 입력하십시오.

db:
  url: jdbc:oracle:thin:@pathToMyDb
  username: someUser
  password: fakePassword

그리고 나는 이런 가치를 다음과 같이 활용할 것입니다 :

@Value("${db.username}") String username

그러나, 나는 결국 이렇게 오류가 발생합니다 :

Could not resolve placeholder 'db.username' in string value "${db.username}"

테스트에서 YAML의 장점을 어떻게 활용할 수 있습니까?

해결법

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

    1.스프링 부트에는 이것에 대한 도우미가 있습니다.

    스프링 부트에는 이것에 대한 도우미가 있습니다.

    @ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
    

    테스트 클래스 또는 추상 테스트 수퍼 클래스의 맨 위에.

  2. ==============================

    2.그것은 언급했듯이 @PropertySource는 yaml 파일을로드하지 않습니다. 이 문제를 해결하려면 사용자가 직접 파일을로드하고로드 된 속성을 환경에 추가하십시오.

    그것은 언급했듯이 @PropertySource는 yaml 파일을로드하지 않습니다. 이 문제를 해결하려면 사용자가 직접 파일을로드하고로드 된 속성을 환경에 추가하십시오.

    ApplicationContextInitializer를 구현하십시오.

    public class YamlFileApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
      @Override
      public void initialize(ConfigurableApplicationContext applicationContext) {
        try {
            Resource resource = applicationContext.getResource("classpath:file.yml");
            YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
            PropertySource<?> yamlTestProperties = sourceLoader.load("yamlTestProperties", resource, null);
            applicationContext.getEnvironment().getPropertySources().addFirst(yamlTestProperties);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
      }
    }
    

    테스트에 이니셜 라이저 추가 :

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class, initializers = YamlFileApplicationContextInitializer.class)
    public class SimpleTest {
      @Test
      public test(){
        // test your properties
      }
    }
    
  3. ==============================

    3.@PropertySource는 속성 파일 만 지원합니다 (Spring 자체의 제한 사항이 아니라 Boot 자체의 제한 사항). JIRA에서 기능 요청 티켓을 자유롭게 열 수 있습니다.

    @PropertySource는 속성 파일 만 지원합니다 (Spring 자체의 제한 사항이 아니라 Boot 자체의 제한 사항). JIRA에서 기능 요청 티켓을 자유롭게 열 수 있습니다.

  4. ==============================

    4.yaml 속성을로드하는 방법 인 IMHO는 다음 두 가지 방법으로 수행 할 수 있습니다.

    yaml 속성을로드하는 방법 인 IMHO는 다음 두 가지 방법으로 수행 할 수 있습니다.

    에이. 기본 경로 인 classpath 루트의 application.yml (일반적으로 src / main / resources)에 설정을 넣을 수 있습니다.이 yaml 등록 정보는 앞서 언급 한 병합 된 경로 이름으로 Spring 부트에 의해 자동으로로드됩니다.

    비. 두 번째 접근법은 좀 더 광범위합니다. 기본적으로 다음과 같이 속성을 보유 할 클래스를 정의합니다.

    @ConfigurationProperties(path="classpath:/appprops.yml", name="db")
    public class DbProperties {
        private String url;
        private String username;
        private String password;
    ...
    }
    

    그래서 본질적으로 이것은 yaml 파일을로드하고 "db"의 루트 요소를 기반으로 DbProperties 클래스를 채우는 것입니다.

    이제 모든 클래스에서 사용하려면 다음을 수행해야합니다.

    @EnableConfigurationProperties(DbProperties.class)
    public class PropertiesUsingService {
    
        @Autowired private DbProperties dbProperties;
    
    }
    

    이 방법들 중 하나는 스프링 부트를 사용하여 깨끗하게 작동해야합니다.

  5. ==============================

    5.Spring Boot 1.4를 사용하면 새로운 @SpringBootTest 주석을 사용하여 스프링 부트 지원을 사용하여 통합 테스트를 부트 스트랩함으로써보다 쉽게 ​​달성 할 수 있습니다 (일반적으로 통합 테스트 설정을 간소화 할 수 있습니다).

    Spring Boot 1.4를 사용하면 새로운 @SpringBootTest 주석을 사용하여 스프링 부트 지원을 사용하여 통합 테스트를 부트 스트랩함으로써보다 쉽게 ​​달성 할 수 있습니다 (일반적으로 통합 테스트 설정을 간소화 할 수 있습니다).

    스프링 블로그에 대한 세부 사항.

    내가 말할 수있는 한, 이것은 클래스 패스에서 YAML 설정을 자동으로 선택하는 것을 포함하여, 프로덕션 코드 에서처럼 Spring Boot의 외부화 된 구성 장점의 모든 이점을 얻는다는 것을 의미합니다.

    기본적으로이 특수 효과는

    필요한 경우 다른 구성 클래스를 지정할 수 있습니다.

    이 특별한 경우에는 @SpringBootTest와 @ActiveProfiles ( "test")를 결합 할 수 있으며 Spring은 일반적인 부트 명명 표준 (즉, application-test.yml)을 따르는 경우 YAML 구성을 선택합니다.

    @RunWith( SpringRunner.class )
    @SpringBootTest
    @ActiveProfiles( "test" )
    public class SpringBootITest {
    
        @Value("${db.username}")
        private String username;
    
        @Autowired
        private MyBean myBean;
    
        ...
    
    }
    

    참고 : SpringRunner.class는 SpringJUnit4ClassRunner.class의 새 이름입니다.

  6. ==============================

    6.또 다른 옵션은 @TestPropertySource를 통해 spring.config.location을 설정하는 것입니다.

    또 다른 옵션은 @TestPropertySource를 통해 spring.config.location을 설정하는 것입니다.

    @TestPropertySource(properties = { "spring.config.location = classpath:<path-to-your-yml-file>" }
    
  7. ==============================

    7.@PropertySource는 factory 인수로 구성 될 수 있습니다. 그래서 당신은 다음과 같이 할 수 있습니다 :

    @PropertySource는 factory 인수로 구성 될 수 있습니다. 그래서 당신은 다음과 같이 할 수 있습니다 :

    @PropertySource(value = "classpath:application-test.yml", factory = YamlPropertyLoaderFactory.class)
    

    YamlPropertyLoaderFactory가 사용자 정의 속성 로더 인 경우 :

    public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
        @Override
        public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
            if (resource == null){
                return super.createPropertySource(name, resource);
            }
    
            return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), null);
        }
    }
    

    https://stackoverflow.com/a/45882447/4527110에서 영감을 얻었습니다.

  8. ==============================

    8.@ActiveProfiles ( "test")를 사용하고 application-test.yml 파일을 src / test / resources에 추가하여 해결 방법을 찾았습니다.

    @ActiveProfiles ( "test")를 사용하고 application-test.yml 파일을 src / test / resources에 추가하여 해결 방법을 찾았습니다.

    그것은 다음과 같이 보였다.

    @SpringApplicationConfiguration(classes = Application.class, initializers = ConfigFileApplicationContextInitializer.class)
    @ActiveProfiles("test")
    public abstract class AbstractIntegrationTest extends AbstractTransactionalJUnit4SpringContextTests {
    
    }
    

    application-test.yml 파일에는 application.yml (src / main / resources에 있음)에서 겹쳐 쓰려는 속성 만 있습니다.

  9. ==============================

    9.snakeyml을 구성하지 않았기 때문입니다. @EnableAutoConfiguration 기능과 함께 제공되는 스프링 부트. 이 주석을 호출 할 때도 snakeyml config가 있습니다.

    snakeyml을 구성하지 않았기 때문입니다. @EnableAutoConfiguration 기능과 함께 제공되는 스프링 부트. 이 주석을 호출 할 때도 snakeyml config가 있습니다.

    이게 내 방법이야:

    @Configuration
    @EnableAutoConfiguration
    public class AppContextTest {
    }
    

    여기에 내 시험이있다.

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(
            classes = {
                    AppContextTest.class,
                    JaxbConfiguration.class,
            }
    )
    
    public class JaxbTest {
    //tests are ommited
    }
    
  10. ==============================

    10.내 코드에 몇 가지 속성을 읽을 필요가 있었고 스프링 부트 1.3.0.RELEASE와 함께 작동합니다.

    내 코드에 몇 가지 속성을 읽을 필요가 있었고 스프링 부트 1.3.0.RELEASE와 함께 작동합니다.

    @Autowired
    private ConfigurableListableBeanFactory beanFactory;
    
    // access a properties.yml file like properties
    @Bean
    public PropertySource properties() {
        PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
        YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
        yaml.setResources(new ClassPathResource("properties.yml"));
        propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
        // properties need to be processed by beanfactory to be accessible after
        propertySourcesPlaceholderConfigurer.postProcessBeanFactory(beanFactory);
        return propertySourcesPlaceholderConfigurer.getAppliedPropertySources().get(PropertySourcesPlaceholderConfigurer.LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME);
    }
    
  11. ==============================

    11.Spring Boot에서 다중 프로필 구성으로 사용자 정의 yml 파일로드.

    Spring Boot에서 다중 프로필 구성으로 사용자 정의 yml 파일로드.

    1) 다음과 같이 SpringBootApplication 시작과 함께 등록 정보 bean을 추가하십시오

    @SpringBootApplication
    @ComponentScan({"com.example.as.*"})
    public class TestApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(TestApplication.class, args);
        }
    
        @Bean
        @Profile("dev")
        public PropertySourcesPlaceholderConfigurer propertiesStage() {
            return properties("dev");
        }
    
        @Bean
        @Profile("stage")
        public PropertySourcesPlaceholderConfigurer propertiesDev() {
            return properties("stage");
        }
    
        @Bean
        @Profile("default")
        public PropertySourcesPlaceholderConfigurer propertiesDefault() {
            return properties("default");
    
        }
       /**
        * Update custom specific yml file with profile configuration.
        * @param profile
        * @return
        */
        public static PropertySourcesPlaceholderConfigurer properties(String profile) {
           PropertySourcesPlaceholderConfigurer propertyConfig = null;
           YamlPropertiesFactoryBean yaml  = null;
    
           propertyConfig  = new PropertySourcesPlaceholderConfigurer();
           yaml = new YamlPropertiesFactoryBean();
           yaml.setDocumentMatchers(new SpringProfileDocumentMatcher(profile));// load profile filter.
           yaml.setResources(new ClassPathResource("env_config/test-service-config.yml"));
           propertyConfig.setProperties(yaml.getObject());
           return propertyConfig;
        }
    }
    

    2) 다음과 같이 Java pojo 객체를 설정한다.

    @Component
    @JsonIgnoreProperties(ignoreUnknown = true)
    @JsonInclude(Include.NON_NULL)
    @ConfigurationProperties(prefix = "test-service")
    public class TestConfig {
    
        @JsonProperty("id") 
        private  String id;
    
        @JsonProperty("name")
        private String name;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }   
    
    }
    

    3) 사용자 정의 yml을 만들고 (다음과 같이 리소스 경로 아래에 놓습니다. YML 파일 이름 : test-service-config.yml

    예 : yml 파일의 구성.

    test-service: 
        id: default_id
        name: Default application config
    ---
    spring:
      profiles: dev
    
    test-service: 
      id: dev_id
      name: dev application config
    
    --- 
    spring:
      profiles: stage
    
    test-service: 
      id: stage_id
      name: stage application config
    
  12. ==============================

    12.Mateusz Balbus 응답 향상.

    Mateusz Balbus 응답 향상.

    YAML 위치가 테스트 클래스마다 정의되는 YamlFileApplicationContextInitializer 클래스 수정. 불행히도 테스트 당 작동하지 않습니다.

    public abstract class YamlFileApplicationContextInitializer
      implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    
      /***
       * Return location of a YAML file, e.g.: classpath:file.yml
       *
       * @return YAML file location
       */
      protected abstract String getResourceLocation();
    
      @Override
      public void initialize(ConfigurableApplicationContext applicationContext) {
        try {
            Resource resource = applicationContext.getResource(getResourceLocation());
            YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
            PropertySource<?> yamlTestProperties = sourceLoader.load("yamlTestProperties", resource, null);
            applicationContext.getEnvironment().getPropertySources().addFirst(yamlTestProperties);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
      }
    }
    

    용법:

    정의 된 getResourceLocation () 메소드를 사용하여 YamlFileApplicationContextInitializer의 하위 클래스를 만들고이 하위 클래스를 @SpringApplicationConfiguration 주석에 추가합니다.

    다음 예제와 같이 테스트 클래스 자체를 특정 하위 클래스로 만드는 것이 가장 쉬운 방법이라고 생각합니다.

    @RunWith(SpringRunner.class)
    @SpringApplicationConfiguration(classes = Application.class, initializers = SimpleTest.class)
    public class SimpleTest extends YamlFileApplicationContextInitializer {
    
      @Override
      protected String getResourceLocation() {
        return "classpath:test_specific.yml";
      }
    
      @Test
      public test(){
        // test your properties
      }
    }
    
  13. from https://stackoverflow.com/questions/21271468/spring-propertysource-using-yaml by cc-by-sa and MIT license