Spring @ConditionalOnProperty 사용법 및 예제
@ConditionalOnProperty 은 단어 그대로 Property의 조건에 따라 작동 하는 bean 이다. 꼭 bean이어야 한다. 예를 들면 우리가 많이 사용하는 StereoType(@Controller, @Service..)은 그것 자체로 bean이어서 이 하위 요소(method level)에 @ConditionalOnProperty 를 붙이면 동작하지 않는다.
사용법
Property란 무엇이냐? Spring 사용시 application.properties나 application.yml에 정의해서 사용하는 값들을 말한다.
예를 들면 이런 application.yml 이 있다.
my:
fruit: banana
my.fruit 이 어떤거냐에 따라서 다른 bean을 생성하고자한다. my.fruit 값이 banana면 banana bean을 생성하고 apple이면 apple bean을 생성하고 싶다. (예제 시나리오 만드는건 너무 어려운것 같다..)
@ConditionalOnProperty(value = "my.fruit", havingValue = "apple", matchIfMissing = false)
@Bean
public String apple() {
return "apple";
}
@ConditionalOnProperty(value = "my.fruit", havingValue = "banana", matchIfMissing = false)
@Bean
public String banana() {
return "banana";
}
이런식으로 @ConditionalOnProperty를 붙여서 application.yml에 있는 값을 기준으로 bean을 생성해줄 수 있다.
my.fruit 값이 banana면 banana bean을 생성하고 apple이면 apple bean을 생성해준다.
여기서 나오는 @ConditionalOnProperty의 속성값들은 ConditionalOnProperty @interface에서 확인 가능하다.
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
/**
* Alias for {@link #name()}.
* @return the names
*/
String[] value() default {};
/**
* A prefix that should be applied to each property. The prefix automatically ends
* with a dot if not specified. A valid prefix is defined by one or more words
* separated with dots (e.g. {@code "acme.system.feature"}).
* @return the prefix
*/
String prefix() default "";
/**
* The name of the properties to test. If a prefix has been defined, it is applied to
* compute the full key of each property. For instance if the prefix is
* {@code app.config} and one value is {@code my-value}, the full key would be
* {@code app.config.my-value}
* <p>
* Use the dashed notation to specify each property, that is all lower case with a "-"
* to separate words (e.g. {@code my-long-property}).
* @return the names
*/
String[] name() default {};
/**
* The string representation of the expected value for the properties. If not
* specified, the property must <strong>not</strong> be equal to {@code false}.
* @return the expected value
*/
String havingValue() default "";
/**
* Specify if the condition should match if the property is not set. Defaults to
* {@code false}.
* @return if the condition should match if the property is missing
*/
boolean matchIfMissing() default false;
}
쉽게 말하자면 다음과 같다.
- name (=value) 속성은 application.yml 의 key
- havingValue 속성은 application.yml의 key에 매핑되는 value
- matchIfMissing 속성은 매칭되는게 없으면 bean을 생성할건지 말건지 결정하는 속성
Test
@RestController
public class TestController {
@Autowired
DefaultListableBeanFactory bf;
@GetMapping("/fruit")
public String getFruit() {
String myFruit = null;
for(String n : bf.getBeanDefinitionNames()){
if("apple".equals(n)) {
myFruit = "my.fruit : apple";
break;
} else if("banana".equals(n)) {
myFruit = "my.fruit : banana";
break;
} else {
myFruit = "my.fruit : unknown";
continue;
}
}
return myFruit;
}
}
위에서 정의한 application.yml과 @ConditionalOnProperty를 정의한 bean이 잘 동작하는지 간단하게 테스트해보는 코드이다. application.yml 파일에 따라 결과가 잘 나온다.
마지막으로 다시 한번 강조하지만 @ConditionalOnProperty는 꼭 bean에 정의를 해줘야 한다.
끝!