log4j2.xml 必须放在类路径根目录(如 src/main/resources),否则回退默认控制台输出;需配齐 slf4j-api、log4j-slf4j2-impl 和 log4j-core;通过 Logger 名称匹配实现多文件输出;异步日志队列满时默认丢弃,需调优参数。

Log4j2 的 log4j2.xml 放哪儿才生效
Log4j2 启动时会按固定顺序查找配置文件,log4j2.xml 必须放在类路径根目录(即 src/main/resources 下),否则自动回退到默认控制台输出,不报错但没日志文件。
- 如果用 Maven,确认该文件在
target/classes/里存在(编译后检查) - 不要放在
src/main/java或子包下,Log4j2 不会扫描 Java 源码路径 - 若同时存在
log4j2.json和log4j2.xml,XML 优先级更高 - 测试是否加载成功:启动时加 JVM 参数
-Dlog4j2.debug=true,看控制台是否有 “Using configuration” 日志
SLF4J 绑定 Log4j2 时为什么报 NoClassDefFoundError: org/slf4j/LoggerFactory
这不是 SLF4J 缺失,而是桥接器或实现未对齐。SLF4J 只是门面,必须配一个具体实现(如 Log4j2),且版本要匹配。
- 确保引入了
slf4j-api(门面) +log4j-slf4j2-impl(桥接器) +log4j-core(实现) - Maven 中避免混用
log4j-slf4j-impl(旧版桥接)和log4j-slf4j2-impl(Log4j2.17+ 推荐) - 运行
mvn dependency:tree | grep slf4j检查是否有多个slf4j-simple或slf4j-log4j12冲突 - 常见错误:只加了
slf4j-api和log4j-core,漏掉桥接器 —— 这会导致 LoggerFactory 找不到实现类
如何让不同模块写入不同日志文件(比如 DAO 层进 dao.log,Service 层进 service.log)
靠 Logger 名称(通常是类全限定名)匹配 log4j2.xml 中的 配置,再绑定专属 。
-
additivity="false"很关键:否则日志会向上委托给 root logger,重复输出 - 每个
对应一个独立的或appender,路径和策略各自定义 - 代码中获取 logger 要用类名:例如
LoggerFactory.getLogger(UserDao.class),才能命中com.example.dao.UserDao这个命名空间 - 注意包名层级:配置
com.example.dao会匹配所有其子包,若只想精确匹配,加includeLocation="false"并配合更细粒度命名
异步日志开启后为什么某些日志丢失或延迟严重
Log4j2 异步日志(AsyncLogger)依赖 LMAX Disruptor,但默认队列满时会丢弃日志(DiscardingAsyncLogger 行为),不是 bug 是设计。
立即学习“Java免费学习笔记(深入)”;
- 检查
log4j2.xml是否用了标签(非)—— 前者才是高性能异步,后者只是简单包装 - Disruptor 队列默认大小为 216(65536),若日志暴增且磁盘慢,队列满后新日志直接丢弃,无警告
- 可通过
-Dlog4j2.asyncLoggerWaitStrategy=Timeout改为阻塞等待,或调大-Dlog4j2.asyncLoggerRingBufferSize=131072 - 异步模式下
Throwable.printStackTrace()可能被截断,建议用logger.error("msg", exception)形式传参










