1.注解@Conditional的定义

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Conditional {/*** All {@link Condition}s that must {@linkplain Condition#matches match}* in order for the component to be registered.*/Class<? extends Condition>[] value();}

注解@Conditional标识一个组件时,该组件只有全面满足value()指定的所有条件时才可以注册到容器中。

注解@Conditional的使用场景如下:

  . 作为类型级别的注解,作用在一个直接或者间接@Component注解(包括@Configuration作为元注解的类)的类上,目标是组成自定义的steretype注解。

  . 作为方法级别的注解,作用在任意的@Bean 方法上

如果一个标注了@Configuration的类,也标注了@Conditional,所有的@Bean方法,@Import和@ComponentScan注解关联的类将也满足这些Conditions。

注意,@Conditional注解不能继承,从父类或者重写方法的condition是不起作用的。

其中,一个Condition是要注册的Bean定义之前可以编程决定的状态。详细信息如下:

2 前生 Condition定义

public interface Condition {/*** Determine if the condition matches.* @param context the condition context* @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}* or {@link org.springframework.core.type.MethodMetadata method} being checked.* @return {@code true} if the condition matches and the component can be registered* or {@code false} to veto registration.*/boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);}

一个单独的condition是一个组件为注册为bean时必须满足matches()方法。

Conditions在要注册的组件变成bean definition之前必须检查立即检查所有的matches方法。

Condition也必须和BeanFactoryPostProcessor一样满足同样的限制条件。更细粒度的控制可以考虑使用ConfigurationCondition。

3.后世

spring-boot-autoconfigure condition相关的类如下:

3.1 ConditionalOnBean定义

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {/*** The class type of bean that should be checked. The condition matches when all of* the classes specified are contained in the {@link ApplicationContext}.* @return the class types of beans to check*/Class<?>[] value() default {};/*** The class type names of bean that should be checked. The condition matches when all* of the classes specified are contained in the {@link ApplicationContext}.* @return the class type names of beans to check*/String[] type() default {};/*** The annotation type decorating a bean that should be checked. The condition matches* when all of the annotations specified are defined on beans in the* {@link ApplicationContext}.* @return the class-level annotation types to check*/Class<? extends Annotation>[] annotation() default {};/*** The names of beans to check. The condition matches when all of the bean names* specified are contained in the {@link ApplicationContext}.* @return the name of beans to check*/String[] name() default {};/*** Strategy to decide if the application context hierarchy (parent contexts) should be* considered.* @return the search strategy*/SearchStrategy search() default SearchStrategy.ALL;}

ConditionalOnBean作用:当指定bean的类名或者名称已经在BeanFactory中存在时才算满足条件。

其实现类为OnBeanCondition,检查指定的bean是存在还是不存在。

@Order(Ordered.LOWEST_PRECEDENCE)
class OnBeanCondition extends SpringBootCondition implements ConfigurationCondition {/*** Bean definition attribute name for factory beans to signal their product type (if* known and it can't be deduced from the factory bean class).*/public static final String FACTORY_BEAN_OBJECT_TYPE = BeanTypeRegistry.FACTORY_BEAN_OBJECT_TYPE;@Overridepublic ConfigurationPhase getConfigurationPhase() {return ConfigurationPhase.REGISTER_BEAN;}@Overridepublic ConditionOutcome getMatchOutcome(ConditionContext context,AnnotatedTypeMetadata metadata) {ConditionMessage matchMessage = ConditionMessage.empty();if (metadata.isAnnotated(ConditionalOnBean.class.getName())) {BeanSearchSpec spec = new BeanSearchSpec(context, metadata,ConditionalOnBean.class);MatchResult matchResult = getMatchingBeans(context, spec);if (!matchResult.isAllMatched()) {String reason = createOnBeanNoMatchReason(matchResult);return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnBean.class, spec).because(reason));}matchMessage = matchMessage.andCondition(ConditionalOnBean.class, spec).found("bean", "beans").items(Style.QUOTE, matchResult.getNamesOfAllMatches());}if (metadata.isAnnotated(ConditionalOnSingleCandidate.class.getName())) {BeanSearchSpec spec = new SingleCandidateBeanSearchSpec(context, metadata,ConditionalOnSingleCandidate.class);MatchResult matchResult = getMatchingBeans(context, spec);if (!matchResult.isAllMatched()) {return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnSingleCandidate.class, spec).didNotFind("any beans").atAll());}else if (!hasSingleAutowireCandidate(context.getBeanFactory(),matchResult.getNamesOfAllMatches(),spec.getStrategy() == SearchStrategy.ALL)) {return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnSingleCandidate.class, spec).didNotFind("a primary bean from beans").items(Style.QUOTE, matchResult.getNamesOfAllMatches()));}matchMessage = matchMessage.andCondition(ConditionalOnSingleCandidate.class, spec).found("a primary bean from beans").items(Style.QUOTE, matchResult.namesOfAllMatches);}if (metadata.isAnnotated(ConditionalOnMissingBean.class.getName())) {BeanSearchSpec spec = new BeanSearchSpec(context, metadata,ConditionalOnMissingBean.class);MatchResult matchResult = getMatchingBeans(context, spec);if (matchResult.isAnyMatched()) {String reason = createOnMissingBeanNoMatchReason(matchResult);return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnMissingBean.class, spec).because(reason));}matchMessage = matchMessage.andCondition(ConditionalOnMissingBean.class, spec).didNotFind("any beans").atAll();}return ConditionOutcome.match(matchMessage);}
}

3.2 ConditionalOnClass

当指定的类在classpath下认定满足条件,实现类为:OnClassCondition。

定义如下:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {/*** The classes that must be present. Since this annotation parsed by loading class* bytecode it is safe to specify classes here that may ultimately not be on the* classpath.* @return the classes that must be present*/Class<?>[] value() default {};/*** The classes names that must be present.* @return the class names that must be present.*/String[] name() default {};}

3.3 ConditionalOnCloudPlatform

指定的云平台激活时满足条件。实现类为:OnCloudPlatformCondition

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnCloudPlatformCondition.class)
public @interface ConditionalOnCloudPlatform {/*** The {@link CloudPlatform cloud platform} that must be active.* @return the expected cloud platform*/CloudPlatform value();}

3.4 ConditionalOnExpression

/*** Configuration annotation for a conditional element that depends on the value of a SpEL* expression.** @author Dave Syer*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnExpressionCondition.class)
public @interface ConditionalOnExpression {/*** The SpEL expression to evaluate. Expression should return {@code true} if the* condition passes or {@code false} if it fails.* @return the SpEL expression*/String value() default "true";}

3.5 ConditionalOnJava

/*** {@link Conditional} that matches based on the JVM version the application is running* on.** @author Oliver Gierke* @author Phillip Webb* @author Andy Wilkinson* @since 1.1.0*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnJavaCondition.class)
public @interface ConditionalOnJava {/*** Configures whether the value configured in {@link #value()} shall be considered the* upper exclusive or lower inclusive boundary. Defaults to* {@link Range#EQUAL_OR_NEWER}.* @return the range*/Range range() default Range.EQUAL_OR_NEWER;/*** The {@link JavaVersion} to check for. Use {@link #range()} to specify whether the* configured value is an upper-exclusive or lower-inclusive boundary.* @return the java version*/JavaVersion value();/*** Range options.*/enum Range {/*** Equal to, or newer than the specified {@link JavaVersion}.*/EQUAL_OR_NEWER,/*** Older than the specified {@link JavaVersion}.*/OLDER_THAN}/*** Java versions.*/enum JavaVersion {/*** Java 1.9.*/NINE(9, "1.9", "java.security.cert.URICertStoreParameters"),/*** Java 1.8.*/EIGHT(8, "1.8", "java.util.function.Function");private final int value;private final String name;private final boolean available;JavaVersion(int value, String name, String className) {this.value = value;this.name = name;this.available = ClassUtils.isPresent(className, getClass().getClassLoader());}/*** Determines if this version is within the specified range of versions.* @param range the range* @param version the bounds of the range* @return if this version is within the specified range*/public boolean isWithin(Range range, JavaVersion version) {Assert.notNull(range, "Range must not be null");Assert.notNull(version, "Version must not be null");switch (range) {case EQUAL_OR_NEWER:return this.value >= version.value;case OLDER_THAN:return this.value < version.value;}throw new IllegalStateException("Unknown range " + range);}@Overridepublic String toString() {return this.name;}/*** Returns the {@link JavaVersion} of the current runtime.* @return the {@link JavaVersion}*/public static JavaVersion getJavaVersion() {for (JavaVersion candidate : JavaVersion.values()) {if (candidate.available) {return candidate;}}return EIGHT;}}}

3.6 ConditionalOnJndi

/*** {@link Conditional} that matches based on the availability of a JNDI* {@link InitialContext} and the ability to lookup specific locations.** @author Phillip Webb* @since 1.2.0*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnJndiCondition.class)
public @interface ConditionalOnJndi {/*** JNDI Locations, one of which must exist. If no locations are specific the condition* matches solely based on the presence of an {@link InitialContext}.* @return the JNDI locations*/String[] value() default {};}

3.7 ConditionalOnMissingBean

/*** {@link Conditional} that only matches when the specified bean classes and/or names are* not already contained in the {@link BeanFactory}.* <p>* The condition can only match the bean definitions that have been processed by the* application context so far and, as such, it is strongly recommended to use this* condition on auto-configuration classes only. If a candidate bean may be created by* another auto-configuration, make sure that the one using this condition runs after.** @author Phillip Webb* @author Andy Wilkinson*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnMissingBean {/*** The class type of bean that should be checked. The condition matches when each* class specified is missing in the {@link ApplicationContext}.* @return the class types of beans to check*/Class<?>[] value() default {};/*** The class type names of bean that should be checked. The condition matches when* each class specified is missing in the {@link ApplicationContext}.* @return the class type names of beans to check*/String[] type() default {};/*** The class type of beans that should be ignored when identifying matching beans.* @return the class types of beans to ignore* @since 1.2.5*/Class<?>[] ignored() default {};/*** The class type names of beans that should be ignored when identifying matching* beans.* @return the class type names of beans to ignore* @since 1.2.5*/String[] ignoredType() default {};/*** The annotation type decorating a bean that should be checked. The condition matches* when each annotation specified is missing from all beans in the* {@link ApplicationContext}.* @return the class-level annotation types to check*/Class<? extends Annotation>[] annotation() default {};/*** The names of beans to check. The condition matches when each bean name specified is* missing in the {@link ApplicationContext}.* @return the name of beans to check*/String[] name() default {};/*** Strategy to decide if the application context hierarchy (parent contexts) should be* considered.* @return the search strategy*/SearchStrategy search() default SearchStrategy.ALL;}

3.8 ConditionalOnMissingClass

/*** {@link Conditional} that only matches when the specified classes are not on the* classpath.** @author Dave Syer*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnMissingClass {/*** The names of the classes that must not be present.* @return the names of the classes that must not be present*/String[] value() default {};}

3.9 ConditionalOnNotWebApplication

/*** {@link Conditional} that only matches when the application context is a not a web* application context.** @author Dave Syer*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnWebApplicationCondition.class)
public @interface ConditionalOnNotWebApplication {}

3.10 ConditionalOnProperty

/*** {@link Conditional} that checks if the specified properties have a specific value. By* default the properties must be present in the {@link Environment} and* <strong>not</strong> equal to {@code false}. The {@link #havingValue()} and* {@link #matchIfMissing()} attributes allow further customizations.** <p>* The {@link #havingValue} attribute can be used to specify the value that the property* should have. The table below shows when a condition matches according to the property* value and the {@link #havingValue()} attribute:** <table summary="having values" border="1">* <tr>* <th>Property Value</th>* <th>{@code havingValue=""}</th>* <th>{@code havingValue="true"}</th>* <th>{@code havingValue="false"}</th>* <th>{@code havingValue="foo"}</th>* </tr>* <tr>* <td>{@code "true"}</td>* <td>yes</td>* <td>yes</td>* <td>no</td>* <td>no</td>* </tr>* <tr>* <td>{@code "false"}</td>* <td>no</td>* <td>no</td>* <td>yes</td>* <td>no</td>* </tr>* <tr>* <td>{@code "foo"}</td>* <td>yes</td>* <td>no</td>* <td>no</td>* <td>yes</td>* </tr>* </table>** <p>* If the property is not contained in the {@link Environment} at all, the* {@link #matchIfMissing()} attribute is consulted. By default missing attributes do not* match.** @author Maciej Walkowiak* @author Stephane Nicoll* @author Phillip Webb* @since 1.1.0*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {/*** Alias for {@link #name()}.* @return the names*/String[] value() default {};/*** A prefix that should be applied to each property. The prefix automatically ends* with a dot if not specified.* @return the prefix*/String prefix() default "";/*** The name of the properties to test. If a prefix has been defined, it is applied to* compute the full key of each property. For instance if the prefix is* {@code app.config} and one value is {@code my-value}, the fully key would be* {@code app.config.my-value}* <p>* Use the dashed notation to specify each property, that is all lower case with a "-"* to separate words (e.g. {@code my-long-property}).* @return the names*/String[] name() default {};/*** The string representation of the expected value for the properties. If not* specified, the property must <strong>not</strong> be equals to {@code false}.* @return the expected value*/String havingValue() default "";/*** Specify if the condition should match if the property is not set. Defaults to* {@code false}.* @return if should match if the property is missing*/boolean matchIfMissing() default false;/*** If relaxed names should be checked. Defaults to {@code true}.* @return if relaxed names are used*/boolean relaxedNames() default true;}

3.11 ConditionalOnResource

/*** {@link Conditional} that only matches when the specified resources are on the* classpath.** @author Dave Syer*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnResourceCondition.class)
public @interface ConditionalOnResource {/*** The resources that must be present.* @return the resource paths that must be present.*/String[] resources() default {};}

3.12 ConditionalOnSingleCandidate

/*** {@link Conditional} that only matches when the specified bean class is already* contained in the {@link BeanFactory} and a single candidate can be determined.* <p>* The condition will also match if multiple matching bean instances are already contained* in the {@link BeanFactory} but a primary candidate has been defined; essentially, the* condition match if auto-wiring a bean with the defined type will succeed.* <p>* The condition can only match the bean definitions that have been processed by the* application context so far and, as such, it is strongly recommended to use this* condition on auto-configuration classes only. If a candidate bean may be created by* another auto-configuration, make sure that the one using this condition runs after.** @author Stephane Nicoll* @since 1.3.0*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnSingleCandidate {/*** The class type of bean that should be checked. The condition match if the class* specified is contained in the {@link ApplicationContext} and a primary candidate* exists in case of multiple instances.* <p>* This attribute may <strong>not</strong> be used in conjunction with {@link #type()}* , but it may be used instead of {@link #type()}.* @return the class type of the bean to check*/Class<?> value() default Object.class;/*** The class type name of bean that should be checked. The condition matches if the* class specified is contained in the {@link ApplicationContext} and a primary* candidate exists in case of multiple instances.* <p>* This attribute may <strong>not</strong> be used in conjunction with* {@link #value()}, but it may be used instead of {@link #value()}.* @return the class type name of the bean to check*/String type() default "";/*** Strategy to decide if the application context hierarchy (parent contexts) should be* considered.* @return the search strategy*/SearchStrategy search() default SearchStrategy.ALL;}

3.13 ConditionalOnWebApplication

/*** {@link Conditional} that matches when the application is a web application. By default,* any web application will match but it can be narrowed using the {@link #type()}* attribute.** @author Dave Syer* @author Stephane Nicoll*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnWebApplicationCondition.class)
public @interface ConditionalOnWebApplication {/*** The required type of the web application.* @return the required web application type*/Type type() default Type.ANY;/*** Available application types.*/enum Type {/*** Any web application will match.*/ANY,/*** Only servlet-based web application will match.*/SERVLET,/*** Only reactive-based web application will match.*/REACTIVE}}

转载于:https://www.cnblogs.com/davidwang456/p/6604112.html

Spring Boot AutoConfiguration注解@ConditionalXXXX之前生今世相关推荐

  1. 40 个 Spring Boot 常用注解

    以下文章来源方志朋的博客,回复"666"获面试宝典 作者 | 谭朝红 链接 | ramostear.com 一.Spring Web MVC 与 Spring Bean 注解 Sp ...

  2. How Spring Boot Autoconfiguration Magic Works--转

    原文地址:https://dzone.com/articles/how-springboot-autoconfiguration-magic-works In my previous post &qu ...

  3. Spring Boot 核心注解与配置文件

    一.入口类与@SpringBootApplication 注解 Spring Boot项目都会有一个*Application 类,这个类作为Spring Boot 项目的入口类,在这个入口类中有mai ...

  4. Spring Boot @Conditional 注解

    Spring Boot @Conditional注解 @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件的才给容器注册Bean. @Conditional ...

  5. idea提示未配置 Spring Boot 配置注解处理器解决方法

    未配置 Spring Boot 配置注解处理器 解决方法: 在pom.xml里添加依赖 <dependency><groupId>org.springframework.boo ...

  6. spring boot 相关注解

    spring boot是基于spring 开发的,因此,spring boot工程中可以使用spring 的注解.除了spring注解外,spring boot会使用到的注解有: @SpringBoo ...

  7. Spring Boot Transactional注解源码阅读笔记(二)

      在源码笔记(一)中,我们留下了几个问题: Spring Boot是怎么扫描到我们的bean里面有 Transactional 这个注解,并且把 InfrastructureAdvisorAutoP ...

  8. Spring Boot核心注解讲解

    Spring Boot最大的特点是无需XML配置文件,能自动扫描包路径装载并注入对象,并能做到根据classpath下的jar包自动配置. 所以Spring Boot最核心的3个注解就是: 1,@配置 ...

  9. Spring Boot 核心注解?主要由哪几个注解组成?

    Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的? 核心注解是@SpringBootApplication,它主要由@SpringBootConfiguration,@EnableA ...

最新文章

  1. 股市币市:数据分析与交易所公告(20190226)
  2. 对于任天堂你了解多少?
  3. memory matlab,memory – 在MATLAB中处理大量结构
  4. 13-Introduction to security
  5. WinDbg实战调试命令笔记
  6. java什么是子类_java什么是子类?
  7. 国际运营版Java区块链交易所源码币币+法币+永续+期权+机器人
  8. 利用建站快速软件包:XAMPP,构建基于winodws平台快速搭建PHP的数据库应用- kimai - 团队时间记录
  9. UVA 10886 Standard Deviation
  10. 关于git远程分支操作
  11. linux系统软件包下载
  12. IBM GPFS并行文件系统
  13. java免费单机游戏中心_虚拟网游(单机游戏)
  14. 计算机制图基本知识6,机械制图基础知识
  15. 给redis设置密码
  16. vscode json文件编辑工具
  17. 上海宝付房价上涨?这几类人倒霉了
  18. 社区网站系统 jsGen
  19. 【Unity】OnTriggerStay2D无法触发问题,物体跟随鼠标等背包系统以及UI场景交互系统技术总结
  20. 猎聘公司管理系统 ——需求规格说明书

热门文章

  1. c语言二fseek从文件头移动_编程C语言文件的随机读写
  2. linux应用程序抢占键盘,linux 系统挂起
  3. 会员直推奖php程序_PHP自适应卡益源码 前台直销源码 报单费 直推奖 有内部商城...
  4. acid php5,ACID原则
  5. 服务器安装系统时无法创建新的分区,重装系统出现“我们无法创建新的分区,也找不到现有的分区”...
  6. MySQL中的浮点数类型和定点数类型
  7. python编程快速上手-----让繁琐工作自动化_每周一书《Python编程快速上手 让繁琐工作自动化》分享!...
  8. 如何备考上海市高等学校计算机一级,如何备考全国计算机一级等级考试
  9. php 24点算法,PHP实现简单的24点游戏
  10. 禄露禄露碌脛脥炉脛锚,学者批时下宫廷戏“就是一堆文化垃圾”