Spring3应用从log4j1迁移至log4j2时抛出NoClassDefFoundError报错
核心结论
- Spring 3.x 原生不支持Log4j2:3.0.x版本仅内置了Log4j 1.x、JUL、SLF4J的日志适配,没有提供Log4j2的原生桥接,这是报错的核心前提。
- 不需要强制升级Spring版本,通过依赖补全+容器类加载配置调整即可解决问题,升级Spring对老旧Ant+Hibernate3项目的兼容成本极高,不优先推荐。
分步解决方案
1. 补全缺失的日志依赖
你目前只引入了log4j-api-2.18.0.jar和log4j-core-2.18.0.jar,缺少Spring3对接Log4j2必须的两个桥接包,需要把同版本的以下jar也放到项目依赖中:
log4j-jcl-2.18.0.jar:对接Spring3默认使用的Jakarta Commons Logging接口,把Spring的日志调用转发到Log4j2log4j-slf4j-impl-2.18.0.jar:对接项目里Hibernate等组件用的SLF4J接口,统一日志输出到Log4j2
2. 配置JBoss 6.4类加载隔离
JBoss EAP 6.4自带日志模块,默认会优先加载容器自身的日志依赖,直接屏蔽war包内的日志jar,这是这类报错最常见的诱因。你需要在war包的WEB-INF目录下新增jboss-deployment-structure.xml配置,强制容器使用应用自带的日志包:
<?xml version="1.0" encoding="UTF-8"?> <jboss-deployment-structure> <deployment> <!-- 排除容器自带的所有日志相关模块 --> <exclusions> <module name="org.apache.log4j"/> <module name="org.slf4j"/> <module name="org.apache.commons.logging"/> <module name="org.jboss.logging"/> </exclusions> <!-- 显式声明加载应用内的日志依赖 --> <resources> <resource-root path="WEB-INF/lib/log4j-api-2.18.0.jar"/> <resource-root path="WEB-INF/lib/log4j-core-2.18.0.jar"/> <resource-root path="WEB-INF/lib/log4j-jcl-2.18.0.jar"/> <resource-root path="WEB-INF/lib/log4j-slf4j-impl-2.18.0.jar"/> </resources> </deployment> </jboss-deployment-structure>
3. 校验Ant打包规则
老旧Ant项目很容易存在打包过滤规则漏拷贝依赖的问题,你需要执行完Ant构建后,解压生成的war包,确认所有上述4个日志jar确实存在于WEB-INF/lib目录下,不要只在子模块的lib目录放包,最终部署包的WEB-INF/lib是web应用类加载优先级最高的依赖目录,子模块自定义的类路径很容易被JBoss的类加载机制忽略。
补充说明
Spring从4.2.1.RELEASE版本开始才原生内置Log4j2的日志适配器,如果后续你有全项目依赖升级的计划,可以升级到Spring4.x以上版本移除额外的桥接包配置,但就当前报错场景而言,不需要做版本升级即可解决问题。
内容的提问来源于stack exchange,提问作者Pracheer Pancholi
相关产品推荐
相关产品推荐

