본문 바로가기
개발/spring, spring boot

[spring] Environment - PropertySource

by 가시죠 2021. 1. 17.
반응형

프로퍼티를 사용하는 이유

실제 업무에서 개발을 할 경우 로컬 환경, 개발 환경, 운영 환경에 따라 DB 연결, 파일 경로 등의 값이 바뀌는데 스프링에서 제공하는 프로퍼티와 프로파일을 이용하여 소스의 변경 없이 편하게 관리 할 수 있다.

 

프로퍼티를 읽어 오는 과정

ConfigurableEnvironment -> MutablePropertySources -> PropertySource(시스템 프로퍼티, 환경변수, 자바 Properties, JNDI)

 

Environment가 제공하는 주요 메서드

  • boolean containsProperty(String key) : 지정한 key에 해당하는 프로퍼티가 존재하는지 확인
  • String getProperty(String key) : 지정한 key에 해당하는 프로퍼티값 구하기, 없을 경우 null
  • String getProperty(String key, String defaultValue) : 지정한 key에 해당하는 프로퍼티 값 구하기, 없을 경우 defaultValue
  • String getRequiredProperty(String key) throws IllegalStateException : 지정한 key에 해당하는 프로퍼티값 구하기, 없을 경우 Exception 발생

 

예제 소스 - 프로퍼티 추가, 프로퍼티 값 가져오기

import org.springframework.core.env.ConfigurableEnvironment;
...

ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
// 또는 ConfigurableApplicationContext = context = new GenericXmlApplicationContext();

// Environment 가져오기
ConfigurableEnvironment env = context.getEnvironment();  

// 프로파일을 dev로 변경
env.setActiveProfiles("dev"); 

// 클래스 패스에 db.properties가 있다고 가정하고 프로퍼티 추가하기
MutablePropertySources propertySources = env.getPropertySources();
propertySources.addLast(new ResourcePropertySource("classpath://db.properties"));

// 이름이 java.version인 프로퍼티 값 가져오기
String javaVersion = env.getProperty("java.version");

 

예제소스 - 애너테이션 기반 프로퍼티 추가

import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource("classpath://db.properties")
public class ConfigByEnv {
  
  @Autowired
  private Environment env;
}


...

//=======================================
// 2개 이상의 프로퍼티 파일을 사용할 경우
//=======================================

// 2개 이상의 프로퍼티 파일을 사용할 경우 @PropertySource의 값을 배열로 지정
@PropertySource(
  value={"classpath:/db.properties, classpath:/file.properties"},
  ignoreSourceNotFound=true // 실제 파일이 없을 경우 익셉션 발생 무시 옵션 (default 값은 false)
)
public class ConfigByEnv {
...
}

// 2개 이상의 프로퍼티 파일을 사용할 경우 @PropertySources를 사용할 수도 있다.
@PropertySources( {
  @PropertySource("classpath:/db.properties"),
  @PropertySource("classpath:/file.properties", ignoreSourceNotFound=true)
} )
public class ConfigByEnv {
...
}

// java8이상일 경우 @PropertySources를 사용하지 않고 @PropertySource를 여러번 사용가능
@PropertySource("classpath:/db.properties")
@PropertySource("classpath:/file.properties", ignoreSourceNotFound=true)
public class ConfigByEnv {
...
}

 

빈에서 Environment 사용하기

EnvironmentAware 인터페이스 구현 하거나 @Autowired 애너테이션을 Environment 필드에 적용

EnvironmentAware 인터페이스 구현 예제

public class ConnectionProvider implements EnvironmentAware {
  private String dirver;
  private String user;
  ...
  private Environment env;
  
  @Override
  public void setEnvironment(Environment env) {
    this.env = env;
  }
  
  public void init() {
    driver = env.getProperty("db.drive");
    user = env.getProperty("db.user");
  }
...
...
  
}

 

@Autowired 애너테이션 사용 예제

public class ConnectionProvider {
  @Autowired
  private Environment env;
  
  private String dirver;
  private String user;
  ...
  
  public void init() {
    driver = env.getProperty("db.dirver");
    user = env.getProperty("db.user");
    ...
  }
...  
}

 

XML에서 프로퍼티 설정 (<context:property-placeholder>) 예제

<beans ...>

  <!-- property-placeholder를 이용하여 프로퍼티 지정 -->
  <context:property-placeholder location="classpath:/db.properties" />
  
  <!-- 프로퍼티 파일이 2개 이상일 경우 콤마로 구분-->
  <context:property-placeholder location="classpath:/db.properties, classpath:/file.properties" />
  
  <!-- 프로퍼티 파일이 2개 이상일 경우 별표이용 -->
  <context:property-placeholder location="classpath:/*.properties" />
  
  <bean id="connProvider"
    class="com.tistory.kisspa.ConnectionProvider" init-method="init">
    
    <!-- 위에서 선언한 placeholder 안의 프로퍼티값을 지정하여 사용 -->
    <property name="driver" value="${db.driver}" />
    <property name="user" value="${db.user}" />

</beans>

property-placeholder 주요 속성

  • file-encoding : 파일 읽어올때 인코딩 지정. 값이 없을 경우 자바 프로퍼티 파일인코딩을 기본값으로 함.
  • ignore-resource-not-found : true일 경우 실제 프로퍼티 파일이 없어서 익셉션이 발생하지 않는다. 기본값은 false
  • ignore-unresolvable : true일 경우 프로퍼티 값을 가져올때 ex, ${db.user} 일치하는 값이 없어서 익셉션 발생X, 기본값은 false

Configuration 애너테이션에서 프로퍼티 사용 예제

@Configuration
public class ConfigByProp {
  @Value("${db.driver}")
  private String driver;
  
  @Value("${db.user}")
  private String user;
  
  @Bean
  public static PropertySourcePlaceholderConfigurer properties() {
    PropertySourcePlaceholderConfigurer configurer = new PropertySourcePlaceholderConfigurer();
    configurer.setLocation(new ClassPathResource("db.properties"));
    return configurer;
  }
  
  @Bean(initMethod = "init")
  public ConnectionProvider connectionProvider() {
    ConnectionProvider conn = new ConnectionProvider();
    conn.setDriver(driver);
    conn.setUser(user);
    ...
  }
}

PropertySourcePlaceholderConfigurer 주요 속성

  • setLocation(Resource location) : location을 프로퍼티 파일로 사용
  • setLocations(Resource[] locations) : locations를 프로퍼티 파일로 사용
  • setFileEncoding(String encoding) : 파일 인코딩을 encoding로 사용
  • setIgnoreResourceNotFound(boolean b) : true일 경우 프로퍼티 파일이 없어서 익셉션 x
  • setIgnoreUnresolvablePlaceholders(boolean b) : true일 경우 프로퍼티 값이 없어도 익셉션 x

 

반응형

댓글