파란하늘의 지식창고
반응형

multi module 환경에서 @PropertySource를 사용하는 방법에 대해 소개한 적이 있다.

2018/12/10 - [Study/Java] - Spring Boot multi module, multi profile 환경에서 @PropertySouce 사용하기

이런 multi module 환경에서 상위 모듈에 지정된 property 값을 특정 모듈에서는 다른 값을 재 지정해서 쓰고 싶은 경우가 있다.

@PropertySource에 order 기능이 있으면 쉽겠지만 아쉽게도 그런 기능은 아직 제공하지 않는다.

따라서 이런 경우 environment에 등록된 propertySource 목록에 대해 순서를 재 지정해 우선순위를 조절해야 한다.

물론 java 내에서 application start 시점에 환경 변수로 사용하는 경우 이런 방법이 문제가 있고 Spring Cloud Config를 사용하는 게 더 좋은 방법이다.

다만 ui 노출 변수 관리 같이 사용 편의성이 좀 더 중요한 경우 아래 방법을 고려해볼 만하다.

@Configuration
@PropertySource(name = "commonModule-ui.properties", value="classpath:commonModule-ui.properties")
public class SomeConfiguration {

    @Autowired
    private ConfigurableEnvironment environment;

    @PostConstruct
    public postConstruct() {
        environment.getPropertySources().forEach(source -> {
    		if (source.getName().startsWith("commonModule-ui")) {
    			environment.getPropertySources().addLast(source);
    		}
    	});
    }
}

@PropertySource에 이름을 지정하지 않으면 value에 설정된 값을 기준으로 자동으로 이름이 생성된다.

위 예제의 경우 name 속성을 생략하였다면 아래 값이 이름으로 설정된다.

class path resource [commonModule-ui.properties]

@Configuration에 설정된 @PropertySource들은 environment의 propertySources에 모두 담긴다.

해당 속성은 MutablePropertySources 타입이며 Iterable Interface이다.

MutablePropertySources는 addFirst, addLast, addBefore, addAfter method를 제공하여 순서를 변경할 수 있게 해 준다.

다만 주의해야 할 점이 있다.

propertySources에는 사용자가 정의한 @PropertySource의 값만 담겨있는 게 아니고 Spring이 기본 사용하는 propertySource도 같이 담겨 있다.

또한 이 값들은 각각 우선순위가 정해져 있다.

https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/html/spring-boot-features.html#boot-features-external-config

  1. Devtools global settings properties in the $HOME/.config/spring-boot folder when devtools is active.
  2. @TestPropertySource annotations on your tests.
  3. properties attribute on your tests. Available on @SpringBootTest and the test annotations for testing a particular slice of your application.
  4. Command line arguments.
  5. Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).
  6. ServletConfig init parameters.
  7. ServletContext init parameters.
  8. JNDI attributes from java:comp/env.
  9. Java System properties (System.getProperties()).
  10. OS environment variables.
  11. A RandomValuePropertySource that has properties only in random.*.
  12. Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).
  13. Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
  14. Application properties outside of your packaged jar (application.properties and YAML variants).
  15. Application properties packaged inside your jar (application.properties and YAML variants).
  16. @PropertySource annotations on your @Configuration classes. Please note that such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins.
  17. Default properties (specified by setting SpringApplication.setDefaultProperties).

spring 문서의 Externalized Configuration 항목을 보면 사용자가 @PropertySource를 사용해 지정하는 propertySource는 16번째로 후 순위로 지정되어 있다.

addFirst를 사용하여 높은 우선순위로 지정하게 되면 application.properties나 command line을 통해 넘어오는 propertySource보다 우선순위가 높게 되어 문제가 발생할 수 있다.

따라서 위에 열거된 순서 중 16번째 순서의 뒷 순서를 지정하여 기존 호출 순서에 영향을 미치지 않는 것이 좋다.

 

 

반응형
profile

파란하늘의 지식창고

@Bluesky_

도움이 되었다면 광고를 클릭해주세요