Spring很常用的@Conditional注解的使用场景和源码解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 今天要分享的是Spring的注解@Conditional,@Conditional是一个条件注解,它的作用是判断Bean是否满足条件,如果满足条件,则将Bean注册进IOC中,如果不满足条件,则不进行注册,这个注解在SpringBoot中衍生出很多注解,比如@ConditionalOnProperty,@ConditionalOnBean,@ConditionalOnClass等等,在SpringBoot中,这些注解用得很多。

介绍


今天要分享的是Spring的注解@Conditional,@Conditional是一个条件注解,它的作用是判断Bean是否满足条件,如果满足条件,则将Bean注册进IOC中,如果不满足条件,则不进行注册,这个注解在SpringBoot中衍生出很多注解,比如@ConditionalOnProperty@ConditionalOnBean@ConditionalOnClass等等,在SpringBoot中,这些注解用得很多。


文件服务场景


下面我们演示一些@Conditional的使用,在软件开发中,文件系统是必须的,但是系统的特点不一样,有些用户希望将文件保存在自己的服务器上,有些用户则没这种要求,这时候,文件可以保存在云上,也可以保存在自建文件系统上,那么面对不同用户的需求,我们的软件也要能够适配不同的环境,只需要简单的配置即可。


假设我们在开发过程中,我们的文件全部托管在云服务厂商的OSS上,代码逻辑也没有预留扩展,那么当用户需要私有化部署,我们可能就需要更改文件存储这边的逻辑,这样的设计是不合理的。


我们想一想,文件存储的代码逻辑是不同的,各个文件系统的实现方式和使用API各不相同,但是它们有一个共性,那就是能够上传文件,下载文件的,所以我们就应该抽象出一个公共接口,下面有不同的实现,比如Minio的文件上传下载等逻辑就使用Minio API去实现,FastDFS就使用FastDFS,OSS就使用OSS,下面我们就编写对应的代码。


编码实现


以下通过编码实现不同文件系统的逻辑实现隔离,统一提供接口的方案,一般我们都会将配置信息写在配置文件中,在配置文件中,使用storageType代表文件存储类型。


文件上传接口


在StorageService接口中,只简单定义了两个方法init()和put(),init()就是做一些初始化操作,比如参数配置,连接等,put()就是上传文件接口。


/**
 * 功能说明: 文件上传接口
 * <p>
 * Original @Author: steakliu-刘牌, 2023-04-03  09:54
 * <p>
 */
public interface StorageService {
    /**
     * 初始化文件存储
     */
    void init();
    /**
     * 上传文件
     * @param file
     */
    void put(MultipartFile file);
}


具体文件系统实现


以下是Minio的具体实现,在类上面使用了@Conditional注解,value值为MinioStorageCondition


@Component
@Conditional(value = MinioStorageCondition.class)
public class MinioStorageService implements StorageService {
    @Override
    public void init() {
        // 初始化操作
    }
    @Override
    public void put(MultipartFile file) {
    }
}


MinioStorageCondition条件判断


MinioStorageCondition的作用就是判断条件是否匹配,它实现Condition接口,要使用@Conditional,其判断类必须要实现Condition接口,然后自己实现matches方法逻辑,以下就是判断storageType是否为minio,如果为minio,那么就返回true,就代表要创建MinioStorageService这个bean,为false则不创建。


public class MinioStorageCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String storageType = context.getEnvironment().getProperty("storageType");
        return "minio".equals(storageType);
    }
}


源码解析


spring在扫描bean的时候,会判断对应的bean是否有@Conditional注解,如果有,则会进入value中的类,进去判断是否符合条件,如果符合,则返回true,就能够注册,实际上如果符合条件,那么就能将BeanDefinition注册进BeanFactory,如果不符合,自然不能注册进。


如下是源码的时序图



从上面的时序图中可以看出,整个过程涉及的类还是挺多的,不过这还不是完整流程,只是从扫描类开始,Spring会扫描工程路径下的类,这个路径可以通过@ComponentScan进行指定,如果是SpringBoot项目,则就为当前工程,然后筛选出需要注册的bean并注册到BeanFactory,对于标注有@Conditional注解的类,会进入@Conditional中value的类中,就是上面的MinioStorageCondition或者FastDFSStorageCondition,然后进行匹配,不满足条件的则不会被注册。


@Conditional的具体流程也比较简单,就不一一赘述,可以看着上面的时序图去看源码实现。


总结


上面对@Conditional的使用,原理等进行简单的介绍,@Conditional注解在SpringBoot中用得还是比较多的,特别是它衍生出来的一些注解,这些注解都是基于它来进行二次封装的,在SpringBoot中,对于很多starter,里面几乎都会有@Conditional和@Conditional衍生注解的使用,我们后续会挑选出一些来说。


今天的分享就到这里,感谢你的观看,我们下期见!


目录
相关文章
|
6天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
8天前
|
搜索推荐 Java Spring
Spring Filter深度解析
【10月更文挑战第21天】Spring Filter 是 Spring 框架中非常重要的一部分,它为请求处理提供了灵活的控制和扩展机制。通过合理配置和使用 Filter,可以实现各种个性化的功能,提升应用的安全性、可靠性和性能。还可以结合具体的代码示例和实际应用案例,进一步深入探讨 Spring Filter 的具体应用和优化技巧,使对它的理解更加全面和深入。
|
22天前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
|
22天前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
21天前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
17 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
21天前
|
Java API Spring
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中过滤器的基础知识和实战项目应用的教程。
19 0
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
|
17天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
46 0
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
22天前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
118 2
|
3月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决

推荐镜像

更多