1. 먼저 true일 경우와 false 일 경우를 테스트
2. 성공,실패할 경우 클래스
-성공할 경우 클래스 Config1
@Configuration
@Conditional(TrueConditon.class)
static class Config1{
@Bean
MyBean myBean(){
return new MyBean();
}
}
@Conditional에 TrueCondition.class엘리먼트 구현
true일 경우 등록시킬 MyBean 생성 - 등록되는지만 확인할 것으로 bean에 내용은 없다
-실패할 경우 클래스 Config2
@Configuration
@Conditional(FalseConditon.class)
static class Config2{
@Bean
MyBean myBean(){
return new MyBean();
}
}
@Conditional에 FalseCondition.class엘리먼트 구현
3. 각각 condition이라는 인터페이스를 구현한 클래스 코딩
static class TrueConditon implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return true;
}
}
static class FalseConditon implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
TrueCondition은 true 반환, FalseCondition은 false 반환
4. 테스트
- true일 경우 테스트 성공
@Test
void conditional() {
//true
AnnotationConfigApplicationContext ac1 = new AnnotationConfigApplicationContext();
ac1.register(Config1.class);
ac1.refresh();
MyBean bean = ac1.getBean(MyBean.class);
}
-false 일 경우 테스트 실패
//false
AnnotationConfigApplicationContext ac2 = new AnnotationConfigApplicationContext();
ac2.register(Config2.class);
ac2.refresh();
MyBean bean2 = ac2.getBean(MyBean.class);
true 랑 똑같이 코딩하여도 아래와 같은 bean 찾을 수 없다는 에러 발생
org.springframework.beans.factory.NoSuchBeanDefinitionException
bean이 생성되지 않았으므로 당연한 결과지만 예외처리 될 수 있게 코딩 변경
//false
ApplicationContextRunner contextRunner = new ApplicationContextRunner();
contextRunner.withUserConfiguration(Config2.class)
.run(context -> {
//Assertions.assertThat(context).hasSingleBean(MyBean.class); 갖고있어야 성공
Assertions.assertThat(context).doesNotHaveBean(MyBean.class); // 갖고있지 않아야 성공
Assertions.assertThat(context).doesNotHaveBean(Config2.class);
});
ApplicationContextRunner : 예외처리
+ 더 나아가 condition을 메타 어노테이션으로 사용하기
아예 어노테이션으로 만들어보기
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Conditional(TrueConditon.class)
@interface TrueConditonal{}
@TrueConditonal
@Configuration
//@Conditional(TrueConditon.class)
static class Config1{
@Bean
MyBean myBean(){
return new MyBean();
}
}
기존에 사용하던 @Coditonal 지우고 성공할 경우 어노테이션인 @TrueConditional을 만들어줌
+ Condition의 조건을 결정한 로직 만들기 - @BooleanConditional
AnnotatedTypeMetadata을 사용하여 true, false 두가지 다 적용할 수 있고
그 조건을 어노테이션 엘리먼트로 지정하는 방법
Boolen으로 true,false 값 전달
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Conditional(BoolenConditon.class)
@interface BoolenConditonal{
boolean value();
}
@Configuration
@BoolenConditonal(true)
//@Conditional(TrueConditon.class)
static class Config1{
@Bean
MyBean myBean(){
return new MyBean();
}
}
@Configuration
@BoolenConditonal(false)
static class Config2{
@Bean
MyBean myBean(){
return new MyBean();
}
}
static class BoolenConditon implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(BoolenConditonal.class.getName());
Boolean value = (Boolean)annotationAttributes.get("value");
return value;
}
}
어노테이션 메타 정보(@BoolenConditonal(true)에 있는 true, false)를 다 가져와 어떤 값을 넣었는지 읽어여함
metadata.getAnnotationAttributes(BoolenConditonal.class.getName());
가져온 후 Boolean값으로 value 값 읽어야함
Boolean value = (Boolean)annotationAttributes.get("value");
최종적으로 코딩이 짧아지고 간결해짐