关于ConditionalOnClass注解
1. pom文件<optional>
标签
在Java开发中,大家肯定在pom文件中添加过依赖(现在没有,以后也肯定会有的),不知道大家对<optional>
标签的了解有多少,或者是你没看下面内容,都不知道optional
单词应该放在什么地方,没关系我会讲,听不懂还可以搜索别的优质博客。
<optional>
标签在pom文件中长这样:
<dependency>
<groupId>com.handsometaoa</groupId>
<artifactId>sms-utool</artifactId>
<version>1.0-SNAPSHOT</version>
<optional>true</optional> <!-- 在这里 -->
</dependency>
它的作用是:当其他模块依赖当前模块时,不会传递依赖 optional
标签值为true的依赖文件,可结合下图理解:
B模块依赖C模块,并提供了BHelloUtils类,其中调用了C模块CHelloUtils的cSayHello
方法,并注意(加粗)B模块pom文件中C依赖项的optional标签值为true。
现在A模块依赖B模块,当调用BHelloUtils中bSayHello
方法,程序会进行报错,提示找不到CHelloUtils,这里就验证了optional的作用。
那我们应该如何调整程序?在A模块pom文件添加C依赖。
2. optional hutool应用实例
空口无凭,Hutool 工具包实现了很多好用的工具,他的扩展工具包就依赖很多了第三方工具包,例如:
2.1 验证
怎么验证?拿emoji举例,没添加emoji-java
依赖,EmojiUtil会爆红(找不到依赖项)。
为什么我们使用hutool工具时,没添加emoji-java
也没显示错误?由于Java是动态加载,在未使用时不会报错。
2.2 设计原因
Hutool开发者考虑到扩展中的内容我们一般不会用到,假如Hutool pom中为默认或者<optional>false</optional>
,当我们引入hutool工具,会相应引入额外的其他依赖(本质上不会使用),也可能会导致依赖冲突(hutool 中依赖版本为1.1.1
,自己项目中版本为 1.0.9
)。
3. ConditioalOnClass
ConditioalOnClass:就是当前类路径下存在该类,才会使标有该注解的类或方法生效
3.1 测试代码结构总览
sms-unite-sdk
中配置类可以这样写,就能实现阿里云、腾讯云短信二选一。
@Configuration
public class SmsConfig {
@Bean
@ConditionalOnClass(name = "com.aliyun.sms.SmsServiceImpl")
public SmsService ailiyunSmsService() {
System.out.println("aliyun smsService init");
return new com.aliyun.sms.SmsServiceImpl();
}
@Bean
@ConditionalOnMissingBean(SmsService.class)
@ConditionalOnClass(name = "com.tencent.sms.SmsServiceImpl")
public SmsService tencentSmsService() {
System.out.println("tx smsService init");
return new com.tencent.sms.SmsServiceImpl();
}
}
4. 关于Spring 自动装配
2.7.x之前:resources 下增加META-INF
文件夹,创建spring.factories
文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.handsometaoa.config.SmsConfig
2.7.x之后:resources 下增加META-INF
文件夹,在其下创建spring
文件夹,最后创建org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件
com.handsometaoa.config.SmsConfig
为了兼容,可以同时写:
在pom文件中
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>2.7.18</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
<exclusions>
<exclusion>
<artifactId>spring-expression</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
<optional>true</optional> <!-- 注意这里,用户引用此模块,spring会自动使用用户的版本 -->
</dependency>
<!-- 省略其他 -->
</dependencies>
5. Demo代码
https://github.com/handsometaoa/condition_on_class-demo (可结合代码、本地执行进行理解)
本文来自博客园,作者:帅气的涛啊,转载请注明原文链接:https://www.cnblogs.com/handsometaoa/p/18190101