1. 먼저 true일 경우와 false 일 경우를 테스트

 

 

2. 성공,실패할 경우 클래스

 

-성공할 경우 클래스 Config1

@Configuration
@Conditional(TrueConditon.class)
static class Config1{
    @Bean
    MyBean myBean(){
        return new MyBean();
    }
}

@Conditional에 TrueCondition.class엘리먼트 구현

true일 경우 등록시킬 MyBean 생성 - 등록되는지만 확인할 것으로 bean에 내용은 없다

static class MyBean{}

 

-실패할 경우 클래스 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");

 

 

최종적으로 코딩이 짧아지고 간결해짐

 

 

'SpringBoot > 프로젝트' 카테고리의 다른 글

Environment properties 적용  (2) 2023.12.06
자동 구성 정보 대체하기  (0) 2023.11.30
[Spring Boot] jetty 서버 구성 추가하기  (0) 2023.11.29
Test Code 작성  (0) 2023.11.27
DI를 이용한 Decorator  (2) 2023.11.27

+ Recent posts