背景

团队所负责的一个项目由于功能的不断累加目前变的十分庞大,打算将其拆分成若干个单独的service,在这之中有一些共用的bean(例如interceptor, datasource等)需要移到一个公共的module中。但是这个公共的module已经被其他service依赖,为了避免对其他service产生未知的影响,需要对bean的加载进行一些限制做到按需加载,为此使用Spring提供的@Conditional注解进行控制。

@ConditionalOnProperty

该注解会根据指定的配置,判断是否加载对应的bean

    @Bean@ConditionalOnProperty(prefix = "spring", name = "example.values",havingValue="true")class ExampleAutoConfiguration {}

在这个例子中,如果存在spring.example.values=true时,会加载ExampleAutoConfiguration。除了prefix,name,havingValue之外,还有一个matchIfMissing属性,该属性表明如果指定的配置不存在,是否加载bean,默认为false。如果有一个bean希望默认情况下都加载,特定值不加载,可以设为true。

@ConditionalOnResource

该注解在指定配置文件存在的情况下加载bean

@Configuration
@ConditionalOnResource(resources = "classpath:conf/apiserver.properties")
public class ApiServerConfigurationFacade {}

需要注意的是仅在classPath下的配置文件才会有效,外部配置文件无法检测

@ConditionalOnClass

只有在classpath中存在指定class是才会加载

@Configuration(proxyBeanMethods = false)
@Import({ NoOpMeterRegistryConfiguration.class, CompositeMeterRegistryConfiguration.class })
@ConditionalOnClass(CompositeMeterRegistry.class)
public class CompositeMeterRegistryAutoConfiguration {}

@ConditionalOnExpression

在满足 SpEL表达式的情况下加载bean

 @ConditionalOnExpression( "'${catalina.home}' != '.' ")public static class Tomcat {}

SpEL表达式在此不做过多介绍,${}中为可以在environment中取到的变量,表达式语法与java类似

@ConditionalOnMissingBean

在指定bean不存的情况下加载bean

 @Bean@ConditionalOnMissingBean(name = "kafkaListenerContainerFactory")ConcurrentKafkaListenerContainerFactory<?, ?> kafkaListenerContainerFactory(ConcurrentKafkaListenerContainerFactoryConfigurer configurer,ObjectProvider<ConsumerFactory<Object, Object>> kafkaConsumerFactory) {ConcurrentKafkaListenerContainerFactory<Object, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();configurer.configure(factory, kafkaConsumerFactory.getIfAvailable(() -> new DefaultKafkaConsumerFactory<>(this.properties.buildConsumerProperties())));return factory;}

该注解主要用在公共模块中,通过该注解可以为其他下游模块提供默认的bean,当下游模块决定自行提供bean时不会导致bean confilct。

@Conditional

如果我们去查看以上注解的源码,可以发现他们都依赖于@Conditional

@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来满足自己的需求。我们有如下两种方式来实现Condition

  • AbstractNestedCondition
  • SpringBootCondition

AbstractNestedCondition

AbstractNestedCondition可以用来组合多个condition,spring提供了三个基类

  • AnyNestedCondition
  • NoneNestedConditions
  • AllNestedConditions

AnyNestedCondition

满足其中任意一个条件都会加载bean,看一个例子

static class DefaultCookieSerializerCondition extends AnyNestedCondition {DefaultCookieSerializerCondition() {super(ConfigurationPhase.REGISTER_BEAN);}@ConditionalOnMissingBean({ HttpSessionIdResolver.class, CookieSerializer.class })static class NoComponentsAvailable {}@ConditionalOnBean(CookieHttpSessionIdResolver.class)@ConditionalOnMissingBean(CookieSerializer.class)static class CookieHttpSessionIdResolverAvailable {}}

NoneNestedConditions

满足其中任意一个条件都会不会加载bean

@Configuration(proxyBeanMethods = false)
@Conditional(MultipleNonPrimaryMeterRegistriesCondition.class)
class CompositeMeterRegistryConfiguration {@Bean@PrimaryAutoConfiguredCompositeMeterRegistry compositeMeterRegistry(Clock clock, List<MeterRegistry> registries) {return new AutoConfiguredCompositeMeterRegistry(clock, registries);}static class MultipleNonPrimaryMeterRegistriesCondition extends NoneNestedConditions {MultipleNonPrimaryMeterRegistriesCondition() {super(ConfigurationPhase.REGISTER_BEAN);}@ConditionalOnMissingBean(MeterRegistry.class)static class NoMeterRegistryCondition {}@ConditionalOnSingleCandidate(MeterRegistry.class)static class SingleInjectableMeterRegistry {}}}

AllNestedConditions

满足所有条件才会加载bean.

SpringBootCondition

上述提到的几个@Conditional注解都是基本SpringBootCondition来实现的,我们可以直接参考spring的源码来实现自己的需求。
也可以参考这位的实现https://blog.csdn.net/wtopps/article/details/84110904

Spring @Conditional注解相关推荐

  1. 一篇文章教你读懂Spring @Conditional注解

    文章目录 一.Conditional简介 二.Conditional用法 1.Conditonal注解作用在方法上 2.Conditonal注解作用在类上 3.类上注入多个条件类 三.Conditio ...

  2. Spring @Conditional注解 详细讲解及示例

    前言: @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean. @Conditional的定义: //此注解可以标注在类和方法上 @Tar ...

  3. Spring Boot2.x-06Spring Boot基础-使用@Conditional注解根据特定的条件装配bean

    文章目录 概述 例子 Step1 实现Condition接口,重写matches方法 Step2 在对应的@Bean上使用@Conditional注解 测试 其他相关的注解 概述 假设在某些特定的场景 ...

  4. Spring系列(六):@Conditional注解用法介绍

    今天给大家介绍@Conditional懒加载注解用法,希望对大家能有所帮助! 1.@Conditional注解介绍 @Conditional是Spring4版本新提供的一种注解,它的作用是按照设定的条 ...

  5. Spring Boot @Conditional 注解

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

  6. 【译】Spring 4.0带来的@Conditional注解

    Spring 4.0带来的@Conditional注解 本文会接触spring 4的新功能:@Conditional注解.在之前的spring版本中,你处理conditions只有以下两个方法: 在3 ...

  7. 【Spring注解】@Conditional注解的使用

    前言 @Conditional注解的判断条件,决定了该类是否可以成为Bean.即使该类被@Component注解修饰,@Conditional条件是false,那么该类也不会注入到IOC容器中.且该注 ...

  8. SpringBoot conditional注解和自定义conditional注解使用

    conditional注解是Springboot starter的基石,自动装配的时候会根据条件确定是否需要注入这个类. 含义:基于条件的注解. 作用:根据是否满足某个特定条件来决定是否创建某个特定的 ...

  9. @data注解_聊一下@Conditional注解系列的作用

    欢迎大家关注我的微信公众号,码猿Bug,或者扫描下方二维码,有需要资料的可以随时联系我 http://weixin.qq.com/r/qig7I1LEOw9ErRZA9324 (二维码自动识别) 今天 ...

最新文章

  1. Attention Model(注意力模型)思想初探
  2. 在 CentOS 7 中安装并使用自动化工具 Ansible
  3. Pinpoint 插件开发
  4. 【转载】Hyperledger学习小结
  5. 使用ssh-keygen和ssh-copy-id三步实现SSH无密码登录
  6. 今天仔细学习了html加载执行的顺序
  7. c++多态相关面试题
  8. 第三方支付账务系统设计难点 16
  9. 从零开始写项目第七篇【搭建Linux环境】
  10. 使用Travis-CI的SpringBoot应用程序的CI / CD
  11. 【Linux】linux下查看目录所在分区
  12. WAIC开发者日倒计时一天,收藏好这份完整日程
  13. HBase 数据迁移
  14. 想学新的编程语言?考虑下 Go 吧!
  15. python动态变量名以及调用_Python 动态变量名与调用介绍
  16. ACL2021 Findings | 挖掘label的语义来增强few-shot问题
  17. java linux ifstat,ifstat命令
  18. 以产品思维去做微信公众号
  19. Angr安装与使用之使用篇(十二)
  20. java keytool下载_JavaJDK自带工具keytool生成ssl证书

热门文章

  1. matlab 相位解包裹,3D轮廓测量中相位解包裹应用
  2. 贵州支教之第五天(11月11日)
  3. DW1000开发笔记(五)DW1000使用轮询方式接收数据
  4. 松下 | 适用于AGV AMR GTP的直流输入伺服MINAS A6V型
  5. 固定焦距的最佳成像计算公式!
  6. tensorflow的freeze graph及inference graph_transforms
  7. Vue项目中强制刷新页面的方法
  8. 360安全卫士极速版和你一起轻松出发 为青少年开启安全护航
  9. 基于JavaEE的影评网管理系统_JSP网站设计_SqlServer数据库设计
  10. 十年后的你会是什么样子?