spring源码 - @Condition原理及运用

news2024/11/19 19:27:33

1.在源码中,在生成beanfinition中有有如一段代码

以下代码逻辑中执行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);
}

2.查看shouldSkip代码逻辑

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;
}

3.从1和2我们可以得到结论

关键在于@Condtion注解中内容的matches方法如果满足才可以继续生成bean

4.@Condition注解代码 

@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); }

5.运用

比如我们在生成类的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根据就没有生成,如下

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

6结论

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/29362.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实验数据处理

来源 加热冷却温度实验&#xff0c;相同实验参数可能有一次或多次重复实验&#xff0c;一次实验中也可能有多次。如何分别每一次周期&#xff0c;并把每个周期的数据都分析出来&#xff0c;成为一个问题。 解决思想 想根据冷却后的平台划分不同周期&#xff0c;但是由于冷却…

web前端期末大作业【仿12306铁路官网首页】学生网页设计作业源码

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

分享5款同类软件中的翘楚,属于是WIN10必备良品

今天要给大家推荐的是5款软件&#xff0c;每个都是同类软件中的个中翘楚,请大家给我高调地使用起来,不用替我藏着掖着。 1.PPT插件——OneKeyTools OK插件是一款免费的PPT插件&#xff0c;让你的PPT制作有无限可能&#xff01;它的功能&#xff0c;太多了&#xff0c;比如图片…

Apache HTTPD 换行解析漏洞(CVE-2017-15715)

漏洞环境 Vulhub 影响版本 Apache 2.4.0~2.4.29 漏洞简介 Apache HTTPD 是一款 HTTP 服务器&#xff0c;其 2.4.0~2.4.29 版本中存在一个解析漏洞&#xff0c;在解析 PHP 时&#xff0c;1.php\x0A 将被按照 PHP 后缀进行解析。 解析漏洞是指服务器应用程序会把某些人为构造…

QT开发实例之常用控件(上)

目录QT控件使用范例设置窗口属性字体形状窗体QPushButton 按钮QLabelQLineEdit 单行文本QComboBox 下拉列表框QFontComboBox 字体下拉列表框QSpinBox 控件QTimeEdit 时间控件QDateEdit 日期控件QScrollBar 滑动条控件QRadioButton 单选按钮QCheckBox 复选框QT控件使用范例 设置…

[附源码]计算机毕业设计JAVA卡牌交易网站

[附源码]计算机毕业设计JAVA卡牌交易网站 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis M…

华为认证HCIP的持证人数

华为认证hcip多少人通过了考试&#xff1f; hcip通过的人数比hcie多很多&#xff1b; 华为官方并没有披露hcip通过的相关数据。 唯一可以借鉴的数据&#xff1a;截止到2020年HCIE的持证人数大约在15000左右。 有多少人过了hcip其实并不是一件非常重要的事&#xff0c;重要的…

[附源码]java毕业设计演唱会售票系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Jan Ozer:高清直播互动场景下的硬编码如何选型?

前言 高清直播逐渐普及&#xff0c;硬编码也成为大势所趋。在 RTE 2022 大会上&#xff0c;来自 NETINT 的 Jan Ozer 通过一系列的对比测试结果&#xff0c;详细分享了如何为高清直播互动场景进行硬编码的技术选型。 本文内容基于演讲内容进行整理&#xff0c;为方便阅读略有删…

膜拜,华为18级工程师用349页构建高可用Linux服务器,其实并不难

前言 本文是华为高级工程师从Linux服务器性能调优与高可用集群构建、MySQL性能调优与高可用架构设计、自动化运维与Linux系统安全等多角度讲解构建高可用Linux服务器的方法和技巧。 希望大家能通过本文掌握 Linux 的精髓&#xff0c;轻松而愉快地工作&#xff0c;从而提高自己…

SwiftUI 后台刷新多个 Section 导致 global index in collection view 与实际不匹配问题的解决

问题现象 在复杂布局的 SwiftUI 视图中,用段(Section)来搭配组合其它容器视图(Form 或 List)无疑极具默契性。不过,在多个 Section 对应的数据被后台多线程修改时,往往会发生难以定位的错误,甚至导致 App 直接崩溃: 如上图所示,我们试图在后台线程更新多个 Section …

[附源码]java毕业设计药品管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

vue3.0的变化汇总

vue2迁移vue3 文档 https://www.javascriptc.com/vue3js/guide/migration/render-function-api.html 1.创建项目 npm init vite-app cd npm install npm run dev 2.setUp() 组合api的&#xff08;解决v2业务逻辑分散的问题&#xff09;方法可以单独写在外面的js。 -本质&…

大数据毕设选题 - 疫情实时数据分析可视化(Flask python)

文章目录1 前言1 课题背景2 数据库设计实现3 实现效果4 Flask框架5 爬虫6 Ajax技术7 Echarts8 最后1 前言 &#x1f525; Hi&#xff0c;大家好&#xff0c;这里是丹成学长的毕设系列文章&#xff01; &#x1f525; 对毕设有任何疑问都可以问学长哦! 这两年开始&#xff0c…

后端学习 - Zookeeper Kafka

实习项目用到了 Kafka&#xff0c;系统学习一下 文章目录Zookeeper一 概述二 数据结构和监听行为三 功能实现1 统一配置管理2 统一命名管理3 分布式锁4 集群管理Kafka一 系统架构1 架构图2 数量关系3 Consumer 重要参数二 工作流程1 消息写入过程2 数据不丢失&#xff1a;ACK、…

邯郸百亿斤粮食生产 国稻种芯·中国水稻节:河北大市粮食经

邯郸百亿斤粮食生产 国稻种芯中国水稻节&#xff1a;河北大市粮食经 记者黄涛、袁柯 人民网石家庄电 杨文娟 科技日报 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 中国农民丰收节国际贸易促进会 国稻种芯中国水稻节 中国三农智库网-功能性农业农业大健康大会报道&…

Android Material Design之MaterialToolbar(三)

上图 引入 implementation com.google.android.material:material:1.4.0属性 属性描述app:menu右侧菜单文件app:navigationIcon左侧返回按钮app:title主标题栏文本app:titleCentered主标题栏文本是否居中app:titleTextColor主标题栏文本颜色app:subtitle子标题栏文本app:s…

OpenSergo ShardingSphere 社区共建微服务视角的数据库治理标准

作者&#xff1a;赵奕豪&#xff08;宿何&#xff09; 为什么需要微服务治理与 OpenSergo&#xff1f; 在经典微服务架构中&#xff0c;我们通常将服务调用中各角色划分为三部分&#xff1a;服务提供者、服务消费者、注册中心。经典的微服务架构可以解决微服务能调通、可以运…

我的家乡潍坊HTML静态网页 学生个人网页设计作品 学生家乡网页模板 简单个人主页成品

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

ESP8266 如何使用 GPIO13 GPIO15 进行 UART0 通信?

1. 修改默认的日志输出串口 UART0 为 UART1 使用 ESP8266 UART1&#xff08;GPIO2&#xff09;作为程序日志输出串口&#xff0c;可进行如下配置&#xff1a; menuconfig -> Component Config -> Common ESP-related Channel for console output -> Custom UARTUART…