복붙노트

[SPRING] application.yml에서 속성을 읽을 때 Spring 프로필이 무시됩니다.

SPRING

application.yml에서 속성을 읽을 때 Spring 프로필이 무시됩니다.

Spring 컨텍스트를 검사하는이 코드가 있습니다.

public void scan() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

    context.register(SomeConfig.class);
    context.refresh();
}

application.yml 파일에서 속성을 읽을 필요가 있으므로 SomeConfig 클래스에서 다음과 같이합니다.

@Configuration
@PropertySource(value = "classpath:application.yml", factory = YamlPropertyLoaderFactory.class)
public class SomeConfig {
  //some beans
}

(여기에서 YamlPropertyLoaderFactory 클래스를 복사했습니다.)

application.yml은 프로필에 의한 몇 가지 속성과 기본 프로필을 가진 일반적인 스프링 부트 파일입니다.

spring:
  profiles:
    active: p1

---

spring:
   profiles: p1

file: file1.txt

---

spring:
   profiles: p2

file: file2.txt

일부 콩에서는 @Value를 사용하여 파일 속성을 읽습니다.

응용 프로그램을 실행할 때 -Dspring.profiles.active = p1 변수를 전달하지만 오류가 발생합니다.

(application.yml에 기본 프로파일이 p1로 설정되어 있기 때문에 프로파일을 넘겨주지 않아도 작동합니다.)

application.yml에서 모든 구성을 제거하면 제대로 작동합니다.

file: file1.txt

즉, 컨텍스트 스캔이 프로필 변수를 읽지 않는다는 의미입니다.

또한 활성 프로필을 "프로그래밍 방식으로"설정하면 속성을 해결하지 못합니다.

context.getEnvironment().setActiveProfiles("p1");

해결법

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

    1.참조하는 YamlPropertyLoaderFactory에는 다음 코드가 있습니다.

    참조하는 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);
        }
    }
    

    YamlPropertySourceLoader.load () 메서드의 세 번째 매개 변수는 실제로 속성을 요구하는 프로필 이름입니다. 이 예제는 null을 전달하므로 특정 프로파일이 아닌 yml 파일에서 속성 집합 만 반환합니다.

    spring:
      profiles:
        active: p1
    
    ---
    

    YamlPropertyLoaderFactory에서 활성 프로파일 이름을 선택하는 것이 쉽지는 않다고 생각합니다.

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

    또는 yml 파일에 활성 프로파일 이름이 있으면 YamlPropertySourceLoader ()를 호출하여 null로로드하여 spring.profiles.active 속성을 가져온 다음 다시 호출하여 원하는 yml 파일의 실제 부분을로드 할 수 있습니다.

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

    YamlPropertySourceLoader는 2018 년 2 월에 다시 변경되었습니다 (YamlPropertySourceLoader는 Git repo의 비난보기). 이제는 propertySource의 목록을 반환하고 load 메서드에 세 번째 매개 변수가 없습니다.

    yml 파일에 spring.profiles.active 속성이 있으면 YamlPropertySourceLoader의 최신 버전에서 다음을 수행 할 수 있습니다.

    public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
    
        @Override
        public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
            if (resource == null){
                return super.createPropertySource(name, resource);
            }
            List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource());
            for (PropertySource<?> checkSource : sources) {
                if (checkSource.containsProperty("spring.profiles.active")) {
                    String activeProfile = (String) checkSource.getProperty("spring.profiles.active");
                    for (PropertySource<?> source : sources) {
                        if (activeProfile.trim().equals(source.getProperty("spring.profiles"))) {
                            return source; 
                        }
                    }
                }
            }
            return sources.get(0);
        }
    
    }
    
  2. ==============================

    2.특정 프로필에 대해서만 속성을 설정하려면 올바른 들여 쓰기가 다음과 같습니다.

    특정 프로필에 대해서만 속성을 설정하려면 올바른 들여 쓰기가 다음과 같습니다.

    spring:
       profiles: p1
       file: file1.txt
    

    위의 경우 $ {spring.file} EL을 사용하여 file1.txt에 액세스 할 수 있습니다.

  3. from https://stackoverflow.com/questions/53117490/spring-profile-is-ignored-when-reading-properties-from-application-yml by cc-by-sa and MIT license