ConfigurationCondition:判断带有@Configuration注解的配置Class是否满足condition条件
所以这2个阶段的枚举的含义也就很明确了:
PARSE_CONFIGURATION:判断是否在解析配置类的时候就进行 condition 条件判断,若失败,则该配置类不注册
REGISTER_BEAN:所有配置类均注册为Bean
默认情况下,带有@Configuration注解的类 为full conguration , phase 为 PARSE_CONFIGURATION,其余方法带有@Bean,或者注解元数据中 带有 @Component,@ComponentScan,@Import,@ImportResource的 为 lite 模式,phase 为REGISTER_BEAN
前言:
最近在看@ConditionalOnBean的时候,看到了ConfigurationCondition接口,对这个接口比较陌生,故了解一下。
介绍:
ConfigurationCondition的定义是这样的,它继承了Condition类,如果读者对Condition类不不熟悉,可以在Spring @Conditional注解 详细讲解及示例 中了解。
package org.springframework.context.annotation;
public interface ConfigurationCondition extends Condition {
ConfigurationCondition.ConfigurationPhase getConfigurationPhase();
//可以翻译为构建阶段
public static enum ConfigurationPhase {
PARSE_CONFIGURATION,
REGISTER_BEAN;
private ConfigurationPhase() {
}
}
}
接口中有一个getConfigurationPhase方法,用来返回ConfigurationPhase枚举类型。
先来看看ConfigurationPhase枚举类型:
官方文档中对它的定义:
The various configuration phases where the condition could be evaluated.
可以评估条件的各种配置阶段。
它有两个值:
PARSE_CONFIGURATION:
Condition应评估@Configuration类,如果此时条件不匹配,@Configuration 则不会添加该类。
REGISTER_BEAN:
该条件不会阻止 @Configuration添加类,在评估条件时,所有@Configurations都将被解析。
Stephane Nicoll在stackoverflow上说到:
ConfigurationCondition is a specialization of Condition for @Configuration classes.
Plain Condition is just fine for 99% of your use cases so you should consider that first. The specialization is really about determining in which phase of the processing of @Configuration classes the condition should be evaluated.
There are two phases:
PARSE_CONFIGURATION evaluates the condition when the @Configuration-annotated class is parsed. This gives a chance to fully exclude the configuration class
REGISTER_BEAN evaluates the condition when a bean from a configuration class is registered. This does not prevent the configuration class to be added but it allows to skip a bean definition if the condition does not match (as defined by the matches method of the Condition interface)
Spring Boot has a OnBeanCondition that basically checks during the registration phase if another bean is present. This is the core of ConditionalOnBean that basically does something when a bean is present
ConfigurationCondition是一个专业化Condition的@Configuration类。
Condition对于99%的用例都很好,所以应该考虑一下。专业化实际上是关于确定应该评估条件的类处理的哪个阶段@Configuration。
有两个阶段:
- PARSE_CONFIGURATION:在@Configuration解析-annotated类时评估条件。这样就有机会完全排除配置类
- REGISTER_BEAN:评估配置类中的bean注册时的条件。这不会阻止添加配置类,但如果条件不匹配(由Condition的matches方法定义),则允许跳过bean定义Condition
Spring Boot OnBeanCondition在注册阶段基本上会检查是否存在另一个bean。这是ConditionalOnBean当bean存在时基本上做的事情的核心
实际在OnBeanCondition中的实现如下:
/**
* 将返回一个REGISTER_BEAN
*/
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.REGISTER_BEAN;
}
我的理解:
ConfigurationPhase的作用就是根据条件来判断是否加载这个配置类,OnBeanCondition(此注解的功能就是判断是否存在某个bean,如果存在,则不注入标注的bean或者类)之所以返回REGISTER_BEAN,是因为需要无论如何都要加载这个配置类(如果是PARSE_CONFIGURATION,则有可能不加载),配置类中的bean的注入需要再根据bean的注入条件来判断。
再者,@onBeanCondition的设计是想如果matches方法返回true,则注入bean,如果返回false则不注入bean。如果枚举值选择了PARSE_CONFIGURATION,matches返回false整个配置将不被加载了,和设计有冲突。
真·总结:
实验证明,ConfigurationPhase的作用并不是根据条件来判断是否加载这个配置类,实际ConfigurationPhase控制的是过滤的时机,是在创建Configuration类的时候过滤还是在创建bean的时候过滤(也可用条件注解的生效阶段来描述)。