Spring的条件注解,一篇文章盘得清清楚楚明明白白
前言
在Spring中,条件注解可根据特定的条件来决定是否创建或配置Bean,这些条件可以基于类、属性、环境等因素。通过使用条件注解,我们可以在Spring容器中更加灵活地管理和控制组件的创建和注入,帮助我们更加灵活地管理和控制Bean的创建和注入,提高代码的灵活性和可维护性。总之,使用很简单,功能很强大。
如果你在项目里有类似下面这样的需求场景,选择使用相关的条件注解,绝对是是非常优雅的实现,没有之一。干货内容呀,如果怕以后找不到,马上收藏+关注吧。
- 自动化配置:根据特定的条件来决定是否创建或配置Bean,例如根据类路径下是否包含特定的库、特定的环境变量是否设置等条件来控制Bean的创建。
- 条件化装配:在Spring容器中,根据条件来决定是否加载某个Bean,例如根据当前所处的环境(如开发、测试、生产)来控制Bean的创建。
- Bean依赖:在Spring容器中,根据条件来决定是否创建依赖的Bean,例如只有当另外某个特定Bean也声明了之后才创建某个Bean。
- 自定义条件:通过实现Condition接口,自定义条件逻辑,根据特定条件来控制Bean的创建行为。
Springboot的相关条件注解大盘点
@ConditionalOnClass:当指定的class存在时,才会注入。
@ConditionalOnMissingClass:当指定的class不存在时,才会注入。
@ConditionalOnProperty:当指定的属性存在于application.properties文件中时,才会注入。
@ConditionalOnResource:当指定的资源文件存在时,才会注入。
@ConditionalOnWebApplication:用于判断当前应用是否为Web应用。
@ConditionalOnNotWebApplication:用于判断当前应用是否非Web应用。
@ConditionalOnBean:当Spring容器中存在指定的Bean时,才会注入。
@ConditionalOnMissingBean:当Spring容器中不存在指定的Bean时,才会注入。
@ConditionalOnSingleCandidate:当Spring容器中存在且仅存在一个指定的Bean时,才会注入。
@ConditionalOnExpression:当SpEL表达式为真时,才会注入。
@ConditionalOnJava:根据Java版本进行判断,不同版本有不同的处理方式。
Springboot的相关条件注解的功能描述与使用
@ConditionalOnClass
@ConditionalOnClass注解的作用是当项目中存在某个类时才会使标有该注解的类或方法生效。这个注解可以用来进行条件判断,以便在特定的类存在时才加载相应的Bean。例如,如果项目中引入了ApacheHttpClient包,那么可以使用@ConditionalOnClass(ApacheHttpClient.class)注解来标识这个Bean,只有当ApacheHttpClient类存在于类路径下时才会构建这个Bean。
在这个示例中,@ConditionalOnClass(ApacheHttpClient.class)注解表示只有当ApacheHttpClient类存在于类路径下时,才会加载HttpClientConfig类中的Bean。如果ApacheHttpClient类不存在,那么HttpClientConfig类中的Bean将不会被创建和注入。
@Configuration
@ConditionalOnClass(ApacheHttpClient.class)
public class HttpClientConfig { @Bean public ApacheHttpClient httpClient() { return new ApacheHttpClient(); }
}
@ConditionalOnMissingClass
@ConditionalOnMissingClass注解的作用是在类路径下不存在指定类时,才会使标有该注解的类或方法生效。这个注解可以用来进行条件判断,以便在特定的类不存在时才加载相应的Bean。例如,如果项目中没有引入MySQL数据库驱动包,那么可以使用@ConditionalOnMissingClass(MySQL.class)注解来标识这个Bean,只有当MySQL类不存在于类路径下时才会构建这个Bean。
@Configuration
@ConditionalOnMissingClass("com.example.NonExistentClass")
public class MyConfig { // Bean definitions go here
}
在这个示例中,@ConditionalOnMissingClass注解表示只有当"com.example.NonExistentClass"这个类不存在时,才会加载MyConfig类中的Bean。如果这个类存在,那么MyConfig类中的Bean将不会被创建和注入。
@ConditionalOnProperty
@ConditionalOnProperty注解的作用是根据指定的属性值来决定是否加载带有该注解的类或方法。如果属性存在且具有指定的值,那么带有@ConditionalOnProperty注解的类或方法将会被加载;否则,将不会加载。它通常用于在Spring应用程序中根据外部配置来决定哪些Bean需要创建和注入。
使用@ConditionalOnProperty注解时,可以通过指定属性名称和属性值来进行条件判断。其中,属性名称可以是应用程序配置文件(如application.properties)中的任意属性,而属性值则可以是任何字符串表达式。当配置文件中的属性值与指定的属性值相匹配时,带有@ConditionalOnProperty注解的类或方法将会被加载。
例如,假设在应用程序的配置文件中有一个名为myapp.database.url的属性,我们希望当该属性的值为jdbc:mysql://localhost:3306/mydb时才加载某个Bean。这时,我们可以在定义该Bean的类中使用@ConditionalOnProperty注解,并指定属性名称和属性值,如下所示:
@Configuration
@ConditionalOnProperty( name = "myapp.database.url", havingValue = "jdbc:mysql://localhost:3306/mydb"
)
public class MyBeanConfig { @Bean public MyBean myBean() { return new MyBean(); }
}
在上面的示例中,当配置文件中的myapp.database.url属性值为jdbc:mysql://localhost:3306/mydb时,MyBeanConfig类中的Bean才会被创建和注入。否则,该Bean将不会被加载。
@ConditionalOnResource
@ConditionalOnResource注解的作用是当指定的资源文件存在时,才会使带有该注解的类或方法生效。它通常用于在Spring应用程序中根据资源文件的存在与否来决定哪些Bean需要创建和注入。
使用@ConditionalOnResource注解时,需要指定资源文件的路径和名称。当应用程序在启动时检测到该资源文件存在时,带有@ConditionalOnResource注解的类或方法将会被加载;否则,将不会加载。
例如,假设我们有一个名为config.properties的配置文件,其中包含了一些应用程序的配置信息。我们希望当该配置文件存在时才加载某个Bean。这时,我们可以在定义该Bean的类中使用@ConditionalOnResource注解,并指定配置文件的路径和名称,如下所示:
@Configuration
@ConditionalOnResource(resources = "config.properties")
public class MyBeanConfig { @Bean public MyBean myBean() { return new MyBean(); }
}
在上面的示例中,当应用程序在启动时检测到config.properties文件存在时,MyBeanConfig类中的Bean才会被创建和注入。否则,该Bean将不会被加载。
@ConditionalOnWebApplication
@ConditionalOnWebApplication注解用于判断当前SpringBoot应用是否为Web应用。根据应用类型,可以进一步确定是否满足某种特定的条件。
使用方式:
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
public class ForMatterAutoConfiguration { // Bean definitions go here
}
在上述示例中,@ConditionalOnWebApplication(type = Type.SERVLET)表示只有当SpringBoot应用类型为SERVLET应用类型时,ForMatterAutoConfiguration才会被加载到Spring容器。
该注解支持以下三种类型:
Type.ANY: 当应用是任何Web应用时,该注解修饰的配置类或方法都会生效。
Type.REACTIVE: 当应用是反应式Web应用(Spring WebFlux)时,该注解修饰的配置类或方法才会生效。
Type.SERVLET: 当应用是基于Servlet的Web应用(Spring MVC)时,该注解修饰的配置类或方法才会生效。
@ConditionalOnNotWebApplication
@ConditionalOnNotWebApplication注解用于判断当前SpringBoot应用是否非Web应用。当应用类型不是Web应用类型时,带有该注解的类或方法将会被加载;否则,将不会加载。
使用方式:
@Configuration
@ConditionalOnNotWebApplication
public class ForMatterAutoConfiguration { // Bean definitions go here
}
在上述示例中,只有当SpringBoot应用类型不是Web应用类型时,ForMatterAutoConfiguration才会被加载到Spring容器。
@ConditionalOnBean
@ConditionalOnBean注解是当Spring容器中有某个Bean时才装配。
这个注解通常用于控制某个Bean的创建和注入,只有当容器中已经存在指定的Bean时,带有该注解的类或方法才会被加载。
使用示例:
@Configuration
@ConditionalOnBean(name = "userBean")
public class MyBeanConfig { @Bean public MyBean myBean() { return new MyBean(); }
}
在上面的示例中,只有当容器中存在名为"userBean"的Bean时,MyBeanConfig类中的myBean()方法才会被创建和注入。
注意:
@ConditionalOnClass和@ConditionalOnBean都是Spring框架中用于条件化配置的注解,但它们的作用和使用场景有所不同。
@ConditionalOnClass注解用于判断classpath下是否存在某个类。当classpath下存在指定类型的类时,带有该注解的类或方法才会被加载。它通常用于在类路径中引入某个类时进行条件判断。
@ConditionalOnBean注解则用于判断Spring容器中是否存在某个Bean。当容器中有指定类型的Bean时,带有该注解的类或方法才会被加载。它通常用于在Spring容器中已有某个Bean时进行条件判断。
总结来说,@ConditionalOnClass和@ConditionalOnBean都用于条件化配置,但前者用于判断classpath下是否存在某个类,后者用于判断容器中是否存在某个Bean。根据实际需求选择使用适当的注解。
@ConditionalOnMissingBean
@ConditionalOnMissingBean注解用于判断Spring容器中是否存在指定类型的Bean。如果容器中不存在该类型的Bean,那么带有该注解的类或方法才会被加载;否则,将不会加载。
使用示例:
@Configuration
@ConditionalOnMissingBean(type = "com.example.MyBean")
public class MyBeanConfig { @Bean public MyBean myBean() { return new MyBean(); }
}
在上面的示例中,只有当容器中不存在类型为"com.example.MyBean"的Bean时,MyBeanConfig类中的myBean()方法才会被创建和注入。否则,该Bean将不会被加载。
需要注意的是,@ConditionalOnMissingBean注解通常用于避免多个配置同时注入的风险。对于自定义的配置类,建议加上@ConditionalOnMissingBean注解,以确保只有当容器中不存在指定类型的Bean时才会加载该配置。
注意:
@ConditionalOnMissingClass和@ConditionalOnMissingBean都用于判断当前上下文是否存在某个对象,如果不存在,则实例化一个Bean。然而,它们分别用于判断类和Bean的存在与否。
@ConditionalOnMissingClass用于判断某个类是否存在于classpath中。当指定的类不存在时,带有该注解的类或方法才会被加载。
@ConditionalOnMissingBean用于判断某个Bean是否存在于Spring容器中。当容器中不存在指定类型的Bean时,带有该注解的类或方法才会被加载。
因此,@ConditionalOnMissingClass和@ConditionalOnMissingBean分别用于不同的场景,需要根据具体需求选择使用。
@ConditionalOnSingleCandidate
@ConditionalOnSingleCandidate注解用于检测容器中是否存在匹配的单个候选Bean。只有当容器中只有单个候选Bean时,带有该注解的类或方法才会被加载;否则,将不会加载。
使用示例:
@Configuration
@ConditionalOnSingleCandidate(MyBean.class)
public class MyBeanConfig { @Bean public MyBean myBean() { return new MyBean(); }
}
在上面的示例中,只有当容器中存在类型为"com.example.MyBean"且只有一个候选Bean时,MyBeanConfig类中的myBean()方法才会被创建和注入。否则,该Bean将不会被加载。
需要注意的是,@ConditionalOnSingleCandidate注解通常用于确保容器中只存在一个指定类型的Bean,以避免多个实例同时存在的情况。对于需要确保单例的Bean,建议使用@ConditionalOnSingleCandidate注解进行条件判断。
@ConditionalOnExpression
@ConditionalOnExpression注解用于根据给定的SpEL(Spring Expression Language)表达式来决定是否加载带有该注解的类或方法。当表达式的结果为true时,该类或方法才会被加载;否则,将不会加载。
使用示例:
@Configuration
@ConditionalOnExpression("${my.feature.enabled:false}")
public class MyFeatureConfig { @Bean public MyFeature myFeature() { return new MyFeature(); }
}
在上面的示例中,当配置文件中的"my.feature.enabled"属性值为true时,MyFeatureConfig类中的myFeature()方法才会被创建和注入。否则,该Bean将不会被加载。
需要注意的是,@ConditionalOnExpression注解通常用于根据配置文件中的属性值来动态决定是否加载某个类或方法。在实际使用中,需要根据具体的业务需求来设置SpEL表达式,以满足不同的条件判断需求。
@ConditionalOnJava
@ConditionalOnJava注解用于根据当前运行的Java版本决定是否加载带有该注解的类或方法。可以根据不同的Java版本来控制不同版本的Bean的创建和注入。
使用示例:
@Configuration
@ConditionalOnJava(9)
public class Java9Config { @Bean public MyJava9Bean myJava9Bean() { return new MyJava9Bean(); }
}
在上面的示例中,只有当当前运行的Java版本为9时,Java9Config类中的myJava9Bean()方法才会被创建和注入。否则,该Bean将不会被加载。
需要注意的是,@ConditionalOnJava注解只能检测当前运行的Java版本,而不能检测其他已安装的Java版本。如果需要检测其他版本的Java,可以使用其他条件判断注解或通过其他方式进行检测。
相关文章:
Spring的条件注解,一篇文章盘得清清楚楚明明白白
前言 在Spring中,条件注解可根据特定的条件来决定是否创建或配置Bean,这些条件可以基于类、属性、环境等因素。通过使用条件注解,我们可以在Spring容器中更加灵活地管理和控制组件的创建和注入,帮助我们更加灵活地管理和控制Bean…...
Oracle (7)Online Redo Log Files
目录 一、Oracle Online Redo Log Files及其相关内容介绍 1、Online Redo Log Files简介 2、Online Redo Log Files特点 3、Online Redo Log Files文件组 4、多路复用文件 5、联机重做日志文件工作方式 6、LGWR什么时候写重做 7、LS和LSN 8、删除Redo文件成员 9、删除…...
物联网AI MicroPython传感器学习 之 PAJ7620手势识别传感器
学物联网,来万物简单IoT物联网!! 一、产品简介 手势识别传感器PAJ7620u2是一款集成3D手势识别和运动跟踪为一体的交互式传感器,传感器可以在有效范围内识别手指的顺时针/逆时针转动方向和手指的运动方向等。它可以识别13种手势&a…...
Affinity Photo 2.2.1 高端专业Mac PS修图软件
Affinity Photo Mac中文版是一款面向专业摄影师和其他视觉艺术家的专业图像处理软件,拥有众多专业高端功能,如Raw处理、PSD导入和导出、16位通道的编辑和ICC色彩管理以及兼容大量图片格式。是现在最快、最顺、最精准的专业修图软件。Affinity Photo Mac是…...
微服务-统一网关Gateway
网关的作用 对用户请求做身份认证、权限校验将用户请求路由到微服务,并实现负载均衡对用户请求做限流 搭建网关服务 创建新module,命名为Gateway,引入依赖(1.SpringCloudGateway依赖;2.Eureka客户端依赖或者nacos的服…...
【音视频|wav】wav音频文件格式详解
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...
网络工程综合试题(二)
1. SR技术有哪些缺点? SR(Segment Routing)技术是一种新兴的网络编程技术,它具有很多优点,但也存在一些缺点,包括: 部署复杂性:SR技术需要对网络进行改造和升级,包括更新…...
Android JNI/NDK 入门从一到二
1. 前言 最基础的创建JNI接口的操作,可以直接看这篇文章 : 第一个Android JNI工程, 本文会基于掌握创建JNI接口的操作的基础之上,来入门JNI/NDK。 2. 在JNI中打印日志 2.1 添加log模块 记得CMake中有log模块,不然编译不过 ta…...
吃瓜教程3|决策树
ID3算法 假定当前样本集合D中第k类样本所占比例为pk,则样本集合D的信息熵定义为 信息增益 C4.5算法 ID3算法存在一个问题,就是偏向于取值数目较多的属性,因此C4.5算法使用了“增益率”(gain ratio)来选择划分属性 CA…...
springboot动态数据源【非伪数据源】
说明:本文章的数据源不是在配置文件中配置两个或多个数据源,在业务方面对这些数据源来回切换,本文章中的数据源是可以动态添加,修改,切换的,废话不多说。 先看工程图: 1.pom.xml文件 <?x…...
如何改善设备综合效率(OEE)并提高工厂的生产力
在现代制造业中,提高设备综合效率(Overall Equipment Efficiency,OEE)是企业追求高效生产和优化生产能力的重要目标之一。OEE是一个关键的绩效指标,可以帮助企业评估设备的利用效率、生产效率和质量水平。本文将从三个…...
一文接入Android阿里Sophix热更新
最近公司项目渐趋成熟,已经不需要经常更新版本,并且更新版本对客户的影响特别大,但是日常维护难免需要更新代码,因此热修复的技术,就比较迫切了。 经过一段时间的对比,我们最终决定使用阿里的Sophix方案&am…...
【高阶数据结构】并查集和图
目录 1.数据结构--并查集 2.数据结构--图 1.图的基础概念 2.图的简单实现 2.1.邻接矩阵的图实现 2.2.邻接表的图实现 2.3.图的DFS和BFS 2.4.最小生成树 2.4.1.Kruskal(克鲁斯卡尔算法) 2.4.2.Prim(普里姆算法) 2.5.最短路径 2.5.1.Dijkstra(…...
Git 提交时提示 GPG 签名错误
本来应该一切都是正常的,但今天提交的时候提示 GPG 签名错误。 错误的信息就是 GPG 签名失败。 gpg: skipped "942395299055675C": No secret key gpg: signing failed: No secret key error: gpg failed to sign the data fatal: failed to write commi…...
vite+vue3实现 tomcat 的本地部署
背景: 很多开发小伙伴在本地开发完前端项目后,碍于服务端环境配置麻烦,想先试试在本地部署,已开发好的前端项目,由于很多文章都是文字性描述,不太直观,为了给大多数新手提供一个教程,…...
docker+playwright
windows10 docker playwright 难点在于windows下docker的安装,以及官方hub被墙的困难。 wsl2 wsl2 ubuntu docker git clone https://gitee.com/lineuman/lcs_playwright.git npm install npx playwright test docker端口怎么映射到主机上面? 设置重…...
php框架路由实现
在PHP中也有很多框架(如Laravel、CodeIgniter)提供了路由功能。下面是一个简单的PHP路由实现原理和示例代码: 路由实现原理: 客户端发起请求,请求的URL会被传递给Web服务器。Web服务器将请求传递给PHP解释器ÿ…...
在CentOS 7中手工打造和运行xml文件配置的Servlet,然后使用curl、浏览器、telnet等三种工具各自测试
下载Openjdk并配置环境变量 https://jdk.java.net/java-se-ri/11-MR2是官网下载Openjdk 11的地方。 sudo wget https://download.java.net/openjdk/jdk11.0.0.1/ri/openjdk-11.0.0.1_linux-x64_bin.tar.gz下载openjdk 11。 sudo mkdir -p /usr/openjdk11创建目录ÿ…...
单例模式.
目录 ♫什么是单例模式 ♫饿汉式单例模式 ♫懒汉式单例模式 ♫单例模式的线程安全问题 ♪原子性 ♪内存可见性与指令重排序 ♫什么是单例模式 单例模式是一种设计模式,通过巧用Java的现有语法,实现一个只能被创建一个实例的类,并提供一个全…...
2023年MathorCup高校数学建模挑战赛大数据挑战赛赛题浅析
比赛时长为期7天的妈杯大数据挑战赛如期开赛,为了帮助大家更好的选题,首先给大家带来赛题浅析,为了方便大家更好的选题。 赛道 A:基于计算机视觉的坑洼道路检测和识别 A题,图像处理类题目。这种题目的难度数模独一档…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...


