[SpringBoot(2)]@Condition 주석

springboot 의 자동화 설정 에서 이 주 해 는 상당히 중요 한 역할 을 합 니 다.
일반적으로@Bean 주해 와 함께 사용 되 며,일정한 조건 을 만족 시 켜 야@Bean 이 수식 한 bean 을 용기 에 주입 하 는 역할 을 합 니 다.
다음은 하나의 예 를 보 겠 습 니 다.classpath 아래 에 어떤 종류 가 있어 야 bean 을 주입 합 니 다.
Condition 인터페이스의 실현 을 정의 합 니 다: 
public class MyCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        try {
            Class> clazz = context.getClassLoader().loadClass("com.liyao.A");
            if (clazz != null) {
                return true;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return false;
    }
}

classpath 에서'com.liyao.A'클래스 를 찾 습 니 다.있 으 면 주입 합 니 다.
다음은 설정 클래스:
class MyBean{

}

@Configuration
public class JavaConfig {

    public static void main(String args[]) {
        ApplicationContext app = new AnnotationConfigApplicationContext(JavaConfig.class);
        MyBean myBean = (MyBean) app.getBean("myBean");
        System.out.println(myBean == null);
    }

    @Bean(name = "myBean")
    @Conditional(MyCondition.class)
    public MyBean getBean() {
        return new MyBean();
    }
}

프로젝트 에 com.liyao.A 의 자바 파일 을 쓰 고 함께 컴 파일 하면 false 를 출력 합 니 다.
클래스 가 없 으 면 noBean 의 이상 을 던 집 니 다.
 
그렇다면@Condition 주 해 는 어떻게 Spring 프레임 워 크 에 의 해 처 리 됩 니까?
이 주 해 는@Configuration 과 함께 사용 되 기 때문에 처리 과정 은@Configuration 을 처리 하 는 BeanFactory PostProcessor,즉 ConfigurationClassPostProcessor 입 니 다.
이 processor 에 서 는 최종 적 으로@Bean 주 해 를 처리 하고 bean 을 등록 합 니 다.등록 하기 전에@Condition 주해 가 있 는 지 확인 하고 match 방법 으로 주입 이 필요 한 지 확인 합 니 다.
	private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
			TrackedConditionEvaluator trackedConditionEvaluator) {

		if (trackedConditionEvaluator.shouldSkip(configClass)) {
			removeBeanDefinition(configClass);
			return;
		}

		if (configClass.isImported()) {
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}
		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}

match 호출 은 condition Evaluator 에서:
		public boolean shouldSkip(ConfigurationClass configClass) {
			Boolean skip = this.skipped.get(configClass);
			if (skip == null) {
				if (configClass.isImported()) {
					if (shouldSkip(configClass.getImportedBy())) {
						// The config that imported this one was skipped, therefore we are skipped
						skip = true;
					}
				}
				if (skip == null) {
					skip = conditionEvaluator.shouldSkip(configClass.getMetadata(),
							ConfigurationPhase.REGISTER_BEAN);
				}
				this.skipped.put(configClass, skip);
			}
			return skip;
		}

	public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) {
		if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
			return false;
		}

		if (phase == null) {
			if (metadata instanceof AnnotationMetadata &&
					ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
				return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
			}
			return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
		}

		for (String[] conditionClasses : getConditionClasses(metadata)) {
			for (String conditionClass : conditionClasses) {
				Condition condition = getCondition(conditionClass, context.getClassLoader());
				ConfigurationPhase requiredPhase = null;
				if (condition instanceof ConfigurationCondition) {
					requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
				}
				if (requiredPhase == null || requiredPhase == phase) {
					if (!condition.matches(context, metadata)) {
						return true;
					}
				}
			}
		}

		return false;
	}

좋은 웹페이지 즐겨찾기