以下代码逻辑中执行this.conditionEvaluator.shouldSkip返回true直接跳出beandefinition生成逻辑
- private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
- @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
- @Nullable BeanDefinitionCustomizer[] customizers) {
-
- AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
- if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
- return;
- }
- abd.setInstanceSupplier(supplier);
- ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
- abd.setScope(scopeMetadata.getScopeName());
- String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
-
- AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
- if (qualifiers != null) {
- for (Class<? extends Annotation> qualifier : qualifiers) {
- if (Primary.class == qualifier) {
- abd.setPrimary(true);
- }
- else if (Lazy.class == qualifier) {
- abd.setLazyInit(true);
- }
- else {
- abd.addQualifier(new AutowireCandidateQualifier(qualifier));
- }
- }
- }
- if (customizers != null) {
- for (BeanDefinitionCustomizer customizer : customizers) {
- customizer.customize(abd);
- }
- }
-
- BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
- definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
- BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
- }
1). 检查class中是否有@Condition注解,没有直接return fase
2). 命出@Condition里内容,直接调用其matches方法,不满足返回true
- public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable 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);
- }
-
- List<Condition> conditions = new ArrayList<>();
- for (String[] conditionClasses : getConditionClasses(metadata)) {
- for (String conditionClass : conditionClasses) {
- Condition condition = getCondition(conditionClass, this.context.getClassLoader());
- conditions.add(condition);
- }
- }
-
- AnnotationAwareOrderComparator.sort(conditions);
-
- for (Condition condition : conditions) {
- ConfigurationPhase requiredPhase = null;
- if (condition instanceof ConfigurationCondition) {
- requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
- }
- if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
- return true;
- }
- }
-
- return false;
- }
关键在于@Condtion注解中内容的matches方法如果满足才可以继续生成bean
- @Target({ElementType.TYPE, ElementType.METHOD})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface Conditional {
-
- /**
- * All {@link Condition} classes that must {@linkplain Condition#matches match}
- * in order for the component to be registered.
- */
- Class extends Condition>[] value();
-
- }
从以下代码可以@Condition中内容其实就是Condition接口实现
public interface Condition { boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }
比如我们在生成类的beandefinition时查看类上有没有@EnableMyImportClass 注解,
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Import(MyDeferredImportSelector.class)
- public @interface EnableMyImportClass {
- String[] value();
- }
没有不让其生成,我们自定义的MyCondition类如下:
- public class MyCondition implements Condition {
- @Override
- public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
- MergedAnnotations mergedAnnotations= metadata.getAnnotations();
- return mergedAnnotations.isDirectlyPresent(EnableMyImportClass.class);
- }
- }
然后在某个类加上这样注解来测试
@Configuration
@PropertySource(value = "classpath:aa.properties")
@EnableMyImportClass({"testme"})
@Conditional(MyCondition.class)
public class AppConfig {
如果我们这里将注解EnableMyImportClass去掉,测试后会发现AppConfig的beandefintion根据就没有生成,如下

如果没有去掉正常情况如下:

从以上的内容可以看出@Condition一个非常实用的注解,可以根据需求在做一些非常定制化的产品加载bean的逻辑,比如在有消息中间件产品中,可以根据系统参数据来判断是否启用对应MQ bean.