本文主要是介绍【SpringBoot(二)】@Condition 注解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在springboot的自动化配置中,这个注解起到了相当重要的作用。
其一般与@Bean注解一起使用,作用就是满足一定条件才将@Bean修饰的bean注入容器。
下面看一个例子,仅仅当classpath下有某一个类才注入bean。
定义一个Condition接口的实现:
public class MyCondition implements Condition {@Overridepublic 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的java文件,一起编译,最终会输出false。
如果没有类会抛出noBean的异常。
那么@Condition注解是如何被Spring框架处理的呢?
因为该注解与@Configuration一起使用,其处理过程是在处理@Configuration的BeanFactoryPostProcessor里,即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的调用在conditionEvaluator里:
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 skippedskip = 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;}
这篇关于【SpringBoot(二)】@Condition 注解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!