解决引入第三方SDK导致的依赖冲突问题

出现问题:

原因:导入第三方sdk

解决思路:刷新maven,清理,排除依赖

在排除掉可能的依赖后发现还是不行,分析依赖关系,打开idea自带的maven树查看工具:

通过maven依赖图谱我们发现,所有的日志依赖都来源于spring-boot-starter,这也是Springboot的祖宗依赖,并且,该sdk是一整个完整的SpringBoot工程,而不是常见的模块式。

直接排他祖宗:

问题解决,分析出现原因:

根本原因:jvm的类加载机制

问题产生过程:两个项目的依赖版本不同,假设我们项目是:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.10</version>
</dependency>

引入的第三方sdk中的依赖是:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

Spring Boot 启动时,类加载器的行为如下:

步骤 1:类加载器扫描 classpath

Spring Boot 启动时,ApplicationClassLoader 负责扫描 classpath 下的 JAR 文件,发现:

  • logback-classic-1.2.10.jar(来自我们的项目依赖)

  • logback-classic-1.2.3.jar(来自 SDK)

Java 规定 同一个类(全限定名相同),只能被一个类加载器加载一次,否则会导致冲突。

步骤 2:类加载器加载 SLF4J

SLF4J 主要涉及以下类:

  • org.slf4j.LoggerFactory (SLF4J 的核心类)

  • org.slf4j.impl.StaticLoggerBinder(绑定具体日志实现)

Spring Boot 在初始化日志时,会执行:

Logger logger = LoggerFactory.getLogger(MyApp.class);

这时,类加载器会加载 org.slf4j.impl.StaticLoggerBinder 类,而这个类分别存在于:

  • logback-classic-1.2.10.jar

  • logback-classic-1.2.3.jar

假设 ApplicationClassLoader 先加载 logback-classic-1.2.3.jar,这时 JVM 缓存了老版本,但你的 logback-classic-1.2.10.jar 中的方法签名可能发生了变化。


3. 发生 AbstractMethodError 的原因

由于 logback-classic-1.2.3.jar较早的版本,它可能没有某些方法,比如:

// 1.2.3 版本的方法
public boolean supportsSourceType(Class<?> sourceType) { return true; }
​
// 1.2.10 版本方法(升级后可能有不同签名)
public boolean supportsSourceType(Class<?> sourceType, boolean flag) { return true; }

然后 Spring Boot 依赖的是 logback-classic-1.2.10.jar 版本的方法:

listenerAdapter.supportsSourceType(someClass);

但由于 logback-classic-1.2.3.jar 已经被类加载器加载,JVM 仍然调用的是老版本的方法,而 logback-classic-1.2.3.jar 里没有这个方法,就会发生 AbstractMethodError

Exception in thread "main" java.lang.AbstractMethodError
    at org.springframework.context.event.GenericApplicationListenerAdapter.supportsSourceType

总结:

  1. 类加载器只能加载一个类的一个版本,如果 logback-classic-1.2.3.jar 先被加载,Spring Boot 调用新版本的方法就会失败。

  2. 方法签名变化导致 AbstractMethodError,因为类加载器仍然引用的是旧的 logback-classic-1.2.3.jar 版本,而新代码需要 1.2.10 的方法。

  3. 该SDK是完整的SpringBoot工程,而不是模块,模块化 SDK 可以通过适当的 类加载器管理、依赖管理、版本对齐 等方式,确保它的日志框架不会影响到 Spring Boot 项目的日志实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值