
本文详解 Spring Boot 中 Log4j2 异步 JDBC Appender 报错 “Unable to write to database” 的根本原因(Spring 环境未注入、配置时机错误、依赖版本冲突),并提供基于 log4j2-spring.xml 的标准化、安全、可运行的配置方案。
本文详解 spring boot 中 log4j2 异步 jdbc appender 报错 “unable to write to database” 的根本原因(spring 环境未注入、配置时机错误、依赖版本冲突),并提供基于 `log4j2-spring.xml` 的标准化、安全、可运行的配置方案。
在 Spring Boot 应用中集成 Log4j2 的异步 JDBC Appender 时,常见错误 ERROR Unable to write to database [...] JDBC connection not available 并非数据库连接本身异常,而是由 Log4j2 配置生命周期与 Spring 容器启动顺序不匹配 导致的典型问题。核心症结在于:Log4j2 在 Spring 上下文初始化完成前即开始加载 log4j2.xml,此时 @Value 注解无法生效,自定义 ConnectionFactory 中的数据库参数全为 null,最终连接创建失败。
✅ 正确做法:使用 log4j2-spring.xml + Spring Lookup
Spring Boot 提供了专用支持机制 —— log4j2-spring.xml(而非 log4j2.xml)。该文件仅在 ApplicationEnvironmentPreparedEvent 事件触发后加载,此时 Spring 环境(如 application.properties)已就绪,可安全使用 ${spring:xxx} 占位符解析配置。
请将原 src/main/resources/log4j2.xml 重命名为:
✅ src/main/resources/log4j2-spring.xml
并替换为以下标准配置(无需自定义 ConnectionFactory 类):
<?xml version="1.0" encoding="UTF-8"?><configuration status="WARN" monitorinterval="30"><appenders><!-- 同步控制台输出(调试用) --><console name="Console" target="SYSTEM_OUT"><patternlayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"></patternlayout></console><!-- JDBC Appender:直接通过 DriverManager 创建连接 --><jdbc name="DatabaseAppender" tablename="LOG_TABLE"><drivermanager connectionstring="${spring:spring.datasource.url}" driverclassname="${spring:spring.datasource.driver-class-name}" username="${spring:spring.datasource.username}" password="${spring:spring.datasource.password}" autocommit="false"></drivermanager><!-- 列映射:注意字段名需与数据库表结构严格一致 --><column name="LOG_LEVEL" isunicode="false" pattern="%level"></column><column name="CLASS_NAME" isunicode="false" pattern="%C"></column><column name="METHOD_NAME" isunicode="false" pattern="%M"></column><column name="LINE_NUMBER" isunicode="false" pattern="%L"></column><column name="MESSAGE" isunicode="false" pattern="%m"></column><column name="THREAD_NAME" isunicode="false" pattern="%t"></column><column name="TIMESTAMP" isunicode="false" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}"></column></jdbc><!-- 异步包装器:缓冲日志事件,提升性能 --><async name="AsyncDatabase" buffersize="262144" includelocation="true"><appenderref ref="DatabaseAppender"></appenderref></async></appenders><loggers><root level="info"><appenderref ref="Console"></appenderref><appenderref ref="AsyncDatabase"></appenderref></root></loggers></configuration>
? 关键说明:
- ${spring:spring.datasource.xxx} 是 Log4j2 Spring Boot 模块提供的 Spring Lookup 功能,仅在 log4j2-spring.xml 中有效;
- DriverManager 方式替代自定义工厂类,彻底规避 Spring Bean 生命周期问题;
- autoCommit="false" 可选,若需事务一致性或批量插入优化可配合 batchSize 使用(需 Log4j2 ≥ 2.17.0)。
⚙️ 必要依赖配置(推荐 Spring Boot 原生管理)
请按以下方式精简并升级 Maven 依赖,避免手动指定易出错的版本:
<dependencies><!-- Web 支持 --><dependency><groupid>org.springframework.boot</groupid><artifactid>spring-boot-starter-web</artifactid></dependency><!-- 替换默认 Logback,启用 Log4j2 --><dependency><groupid>org.springframework.boot</groupid><artifactid>spring-boot-starter-log4j2</artifactid><scope>runtime</scope></dependency><!-- Oracle JDBC Driver(运行时依赖) --><dependency><groupid>com.oracle.database.jdbc</groupid><artifactid>ojdbc8</artifactid><scope>runtime</scope></dependency><!-- 可选:如需 Async Logger(非 Async Appender),才需 disruptor --><!-- <dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.4</version>
<scope>runtime</scope>
</dependency> --></dependencies>
✅ 优势:
- spring-boot-starter-log4j2 自动引入兼容版本的 log4j-core(当前 Spring Boot 2.7.x 对应 Log4j2 2.17.2+),修复 CVE-2021-44228 等高危漏洞;
- 移除手动管理的 log4j-core 和 log4j-api,避免版本冲突;
- log4j-spring-boot 依赖在 Spring Boot 2.7+ 中已内置,无需显式声明。
⚠️ 注意事项与验证步骤
-
数据库表必须预先创建(以 Oracle 为例):
CREATE TABLE LOG_TABLE ( ID NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, LOG_LEVEL VARCHAR2(10), CLASS_NAME VARCHAR2(255), METHOD_NAME VARCHAR2(255), LINE_NUMBER NUMBER, MESSAGE CLOB, THREAD_NAME VARCHAR2(255), TIMESTAMP DATE ); -
确保 application.properties 中配置正确且无拼写错误:
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe spring.datasource.username=test spring.datasource.password=test spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver # 不需要 logging.config=... — Spring Boot 会自动发现 log4j2-spring.xml
启动时检查日志:成功加载后应看到类似提示:
INFO Using configuration file [log4j2-spring.xml]
而非 WARN Unable to locate configuration。异步 vs 异步日志器:本文使用的是 异步 Appender(
包裹 JDBC),它已足够满足大多数场景性能需求;若追求极致吞吐,可改用 ,但需额外引入 disruptor 并重构 logger 配置。
通过以上调整,Log4j2 将在 Spring 环境完全就绪后初始化 JDBC 连接,彻底解决 JDBC connection not available 错误,实现稳定、安全、高性能的日志异步落库。











