使用Log4j 1.x桥接器遇类缺失错误,求Log4j2兼容方案
如何在使用Log4j2的同时兼容依赖Log4j 1.x的第三方包?
问题场景
我想在项目中使用性能更优的Log4j2,但项目依赖的第三方Jar包依赖Log4j 1.x和slf4j-log4j12,导致启动时出现日志相关警告。
已执行的操作
按照Log4j2迁移文档指导,我先排除了slf4j-log4j12依赖:
<exclusion> <artifactId>slf4j-log4j12</artifactId> <groupId>org.slf4j</groupId> </exclusion>
然后添加了以下Log4j2相关依赖:
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <scope>runtime</scope> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-1.2-api</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.4.2</version> </dependency>
遇到的错误
运行程序时,第三方包内的服务无法启动,抛出类找不到异常:
Caused by: java.lang.ClassNotFoundException: org.slf4j.impl.Log4jLoggerAdapter at java.net.URLClassLoader.findClass(URLClassLoader.java:387) at java.lang.ClassLoader.loadClass(ClassLoader.java:419) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
问题原因
org.slf4j.impl.Log4jLoggerAdapter是slf4j-log4j12包中的类,第三方包可能直接硬编码引用了这个类(而非通过SLF4J标准API调用),所以排除slf4j-log4j12后会找不到该类。
修复方案
不需要完全排除slf4j-log4j12,而是通过依赖优先级让Log4j2的桥接包接管日志逻辑,同时保留slf4j-log4j12提供缺失的类:
1. 调整Maven依赖配置
修改后的依赖如下:
<!-- SLF4J 核心API --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <!-- Log4j2 核心与API --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j.version}</version> <scope>runtime</scope> </dependency> <!-- 桥接SLF4J调用到Log4j2 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.version}</version> </dependency> <!-- 桥接Log4j 1.x API调用到Log4j2 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-1.2-api</artifactId> <version>${log4j.version}</version> </dependency> <!-- 显式声明slf4j-log4j12,解决硬编码类引用问题 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> <optional>true</optional> <!-- 避免传递给上层项目 --> </dependency> <!-- Disruptor用于Log4j2异步日志优化 --> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.4.2</version> <scope>runtime</scope> </dependency>
2. 验证依赖树
执行mvn dependency:tree命令,确认:
log4j-slf4j-impl和log4j-1.2-api使用你指定的Log4j2版本slf4j-log4j12的版本与slf4j-api保持一致
3. 核心逻辑说明
log4j-1.2-api会接管所有Log4j 1.x API的调用,将日志请求转发到Log4j2核心log4j-slf4j-impl会接管SLF4J的标准API调用,同样转发到Log4j2- 保留
slf4j-log4j12是为了给硬编码引用Log4jLoggerAdapter的第三方包提供类,但实际日志输出仍由Log4j2处理
内容的提问来源于stack exchange,提问作者pieere yu
相关产品推荐
相关产品推荐

