static Inner 클래스 : static이 붙으면 중첩되어 있는 클래스이긴 하지만 바깥쪽에 있는 클래스와 직접적으로 아무 관련없는 평범한 클래스와 같음. 바깥 클래스가 패키지 역할을 해준다고 생각하면 됨
**AnnotationConfigApplicationContext : ****Java 기반의 설정 클래스를 사용하여 빈(Bean) 객체를 설정하고 관리하는 역할을 수행
public class ConditionalTest {
@Test
public void conditional() {
// true
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.register(Config1.class);
ac.refresh();
MyBean bean = ac.getBean(MyBean.class);
// false
AnnotationConfigApplicationContext ac2 = new AnnotationConfigApplicationContext();
ac2.register(Config2.class);
ac2.refresh();
MyBean bean2 = ac2.getBean(MyBean.class);
}
@Configuration
@Conditional(TrueCondition.class)
static class Config1 {
@Bean
MyBean myBean() {
return new MyBean();
}
}
@Configuration
@Conditional(FalseCondition.class)
static class Config2 {
@Bean
MyBean myBean() {
return new MyBean();
}
}
static class MyBean {}
static class TrueCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return true;
}
}
static class FalseCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
}
위처럼 getBean()을 사용하지 않고 테스트 목적으로 만들어진 Bean 등록여부 확인하기위해 테스트 Assert Lilbrary의 테스트 전용 ApplicationContext 구현을 사용 → ApplicationContextRunner
public class ConditionalTest {
@Test
public void conditional() {
// true
ApplicationContextRunner contextRunner = new ApplicationContextRunner();
contextRunner.withUserConfiguration(Config1.class)
.run(context -> {
Assertions.assertThat(context).hasSingleBean(MyBean.class);
Assertions.assertThat(context).hasSingleBean(Config1.class);
});
// false
ApplicationContextRunner contextRunner2 = new ApplicationContextRunner();
contextRunner2.withUserConfiguration(Config2.class)
.run(context -> {
Assertions.assertThat(context).doesNotHaveBean(MyBean.class);
Assertions.assertThat(context).doesNotHaveBean(Config2.class);
});
}
@Configuration
@Conditional(TrueCondition.class)
static class Config1 {
@Bean
MyBean myBean() {
return new MyBean();
}
}
@Configuration
@Conditional(FalseCondition.class)
static class Config2 {
@Bean
MyBean myBean() {
return new MyBean();
}
}
static class MyBean {}
static class TrueCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return true;
}
}
static class FalseCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
}
확인하고 싶은 조건을 가진 @Conditional 애너테이션을 새롭게 정의
public class ConditionalTest {
@Test
public void conditional() {
// true
ApplicationContextRunner contextRunner = new ApplicationContextRunner();
contextRunner.withUserConfiguration(Config1.class)
.run(context -> {
Assertions.assertThat(context).hasSingleBean(MyBean.class);
Assertions.assertThat(context).hasSingleBean(Config1.class);
});
// false
ApplicationContextRunner contextRunner2 = new ApplicationContextRunner();
contextRunner2.withUserConfiguration(Config2.class)
.run(context -> {
Assertions.assertThat(context).doesNotHaveBean(MyBean.class);
Assertions.assertThat(context).doesNotHaveBean(Config2.class);
});
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Conditional(TrueCondition.class)
@interface TrueConditional {}
@Configuration
@TrueConditional
static class Config1 {
@Bean
MyBean myBean() {
return new MyBean();
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Conditional(FalseCondition.class)
@interface FalseConditional {}
@Configuration
@FalseConditional
static class Config2 {
@Bean
MyBean myBean() {
return new MyBean();
}
}
static class MyBean {}
static class TrueCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return true;
}
}
static class FalseCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
}
@Conditional 애너테이션을 만들어서 true와 false 두가지 모두 element로 지정할 수 있는 방식