====== PropertySource ======
* [[http://blog.springsource.org/2011/02/15/spring-3-1-m1-unified-property-management/|Spring 3.1 M1: Unified Property Management]]
* Spring 3.1 부터 생기기 시작한 통합 프라퍼티 관리 시스템
* 시스템 프라퍼티, 환경변수, JNDI 등을 모두 하나의 공간에 넣고 그 값을 읽고 설정할 수 있게 해준다.
* [[http://scottfrederick.blogspot.kr/2012/03/custom-propertysource-in-spring-31.html|Custom PropertySource in Spring 3.1]] : 프라퍼티 소스에 Redis의 데이터를 추가하는 예제
* [[http://blog.codeleak.pl/2015/09/placeholders-support-in-value.html|${... } placeholders support in @Value annotations in Spring]]
===== 프라퍼티 추가 =====
* 일반 프라퍼티 파일의 경우
* Java 클래스 설정에서는 [[http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/PropertySource.html|@PropertySource]]로 프라퍼티 파일을 지정하거나,
* [[http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/xsd-config.html#xsd-config-body-schemas-context-pphc| tag]]를 사용해 넣을 수 있다. - 이거 안 된다. 하단 참조.
===== 코딩을 통한 임의의 프라퍼티 소스 추가 =====
* ''MyPropertySource''가 [[http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/core/env/PropertySource.html|PropertySource]] 구현체 일 때
==== 일반 Java 애플리케이션 ====
ConfigurableApplicationContext ctx = new GenericApplicationContext();
MutablePropertySources sources = ctx.getEnvironment().getPropertySources();
sources.addFirst(new MyPropertySource());
==== 웹 애플리케이션 ====
* ''web.xml''
contextInitializerClasses
com.bank.MyInitializer
* TestContext에서 ''web.xml''없이 Java Code로 등록하기
@ContextConfiguration(initializers = MyInitializer.class)
* ''MyInitializer.java''
public class MyInitializer implements ApplicationContextInitializer {
public void initialize(ConfigurableWebApplicationContext ctx) {
PropertySource ps = new MyPropertySource();
ctx.getEnvironment().getPropertySources().addFirst(ps);
// perform any other initialization of the context ...
}
}
==== ApplicationContextInitializer를 Java 코드 기반 ApplicationContext에서 사용하기 ====
* [[http://stackoverflow.com/questions/13288841/applicationcontextinitializer-in-a-non-web-spring-context|java - ApplicationContextInitializer in a non-web Spring Context?]]
// Create context, but dont initialize with configuration by calling
// the empty constructor. Instead, initialize it with the Context Initializer.
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
MyAppContextInitializer initializer = new MyAppContextInitializer();
// ApplicationContextInitializer가 ApplicationContext를 초기화해주는 형태
initializer.initialize( ctx );
// @Configuration 클래스를 등록하고 초기화
ctx.register( com.my.classpath.StackOverflowConfiguration.class );
ctx.refresh()
==== @Configuration 클래스에서 XML 프라퍼티를 프라퍼티 소스로 등록하기 예제 ====
**3.2 최신 버전에서는 이 기법을 사용할 필요가 없다. ApplicationContextInitializer를 사용하자.**
현재(3.1.2) ''@PropertySource''를 통해서는 XML 프라퍼티를 등록할 수 없는 상태인데, ''@Configuration'' Java 클래스에서 직접 등록할 수 있다.
[[http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/ConfigurableApplicationContext.html|ConfigurableApplicationContext]]를 주입 받은 것에 주의하라. ApplicationContext로 주입 받으면 안 된다. 프라퍼티 소스의 이름도 겹치면 안 된다.
@Configuration
public class SpringConfig {
@Autowired
private org.springframework.context.ConfigurableApplicationContext applicationContext;
@Autowired
private org.springframework.core.io.ResourceLoader resourceLoader;
@PostConstruct
public void addXmlProperties() throws Exception {
addXmlProperties("classpath:my-properties.xml");
addXmlProperties("classpath:my-properties2.xml");
}
private void addXmlProperties(String location) throws IOException,
InvalidPropertiesFormatException {
Resource resource = resourceLoader.getResource(location);
Properties properties = new Properties();
properties.loadFromXML(resource.getInputStream());
applicationContext
.getEnvironment()
.getPropertySources()
.addLast(
new PropertiesPropertySource(
getNameForResource(resource), properties));
}
// from ResourcePropertySource
private static String getNameForResource(Resource resource) {
String name = resource.getDescription();
if (!StringUtils.hasText(name)) {
name = resource.getClass().getSimpleName() + "@"
+ System.identityHashCode(resource);
}
return name;
}
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
===== PlaceHolder로 사용하기 =====
PropertySource에 등록된 프라퍼티들을 ''@Value("${property.name}")'' 형태로 사용하려면 [[http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.html|PropertySourcesPlaceholderConfigurer]] 등록이 필요하다.
* Java 코드 설정시
@Configuration
@PropertySource("my.properties")
public class SpringConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
* XML로 설정시
===== ResourceLoader =====
* ''@Autowired ResourceLoader resourceLoader'' 로 현재 애플리케이션 컨텍스트의 [[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/io/ResourceLoader.html|ResourceLoader]]를 획득하여 사용할 수 있다.
* 단, ''classpath:/package/to/**/*.xml'' 처럼 Pattern화된 Resource를 로딩할 때는 [[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/io/support/ResourcePatternResolver.html|ResourcePatternResolver]]를 주입받아서 [[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/io/support/ResourcePatternResolver.html#getResources-java.lang.String-|ResourcePatternResolver#getResources()]] 메소드로 패턴을 해석한 결과를 획득해야 한다.
* 그냥 속 편하게 [[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html|ApplicationContext]]를 주입 받으면 이것 자체가 ''ResourcePatternResolver''를 구현하므로 이를 사용하도 된다.
===== @Value =====
==== @Value로 Date 객체 주입하기 ====
* [[http://stackoverflow.com/questions/18066482/inject-date-using-value-annotation|spring - Inject date using @Value annotation - Stack Overflow]]
@Value("#{new java.text.SimpleDateFormat(\"yyyyMMdd\").parse(\"${PROP_DATE}\")}")
private Date date;
* [[http://www.baeldung.com/spring-value-defaults|Using Spring @Value with Defaults]]