在 Java 日誌生態中,Logger.getLogger() (Log4j/Log4j2 原生 API) 與 LogFactory.getLog() (Commons Logging / JCL) 是兩種最常見的日誌獲取方式。它們分別代表「具體實現綁定」與「門面抽象」兩種設計哲學,選型直接影響專案的靈活度與維護成本。
| 維度 | Logger.getLogger() (Log4j 原生) | LogFactory.getLog() (JCL 門面) |
|---|---|---|
| 所屬體系 | Log4j / Log4j2 具體實現 | Commons Logging (JCL) 抽象門面 |
| 綁定程度 | 強綁定 特定日誌實現 | 弱綁定 運行時動態發現 |
| 底層實現 | 直接使用 Log4j Logger | 自動遞歸查找:Log4j → JUL → SimpleLog |
| 配置方式 | log4j.properties / log4j2.xml | commons-logging.properties + 底層實現配置 |
| 類別載入機制 | 標準類別載入 | 線程上下文類別載入器 (TCCL) 掃描 |
| 典型應用場景 | 獨立應用、Log4j 深度用戶 | 框架開發、多模組專案、需切換日誌實現 |
// === Log4j 原生 API (強綁定) ===
import org.apache.log4j.Logger;
public class Log4jNativeExample {
// 通常傳入當前類別,支援按類別分級配置
private static final Logger logger = Logger.getLogger(Log4jNativeExample.class);
public void doBusiness() {
logger.info("業務處理開始");
logger.debug("詳細除錯信息");
}
}
// === Commons Logging (JCL) 門面 API (弱綁定) ===
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class JclExample {
private static final Log log = LogFactory.getLog(JclExample.class);
public void doBusiness() {
log.info("業務處理開始");
log.debug("詳細除錯信息");
}
}
LogFactory.getLog() 內部執行以下查找順序 (類別載入器層級):
org.apache.commons.logging.Log 實現類 (由 commons-logging.properties 指定)org.apache.commons.logging.impl.Log4jLogger (若類路徑有 Log4j)org.apache.commons.logging.impl.Jdk14Logger (Java Util Logging - JUL)org.apache.commons.logging.impl.SimpleLog (控制台輸出,無需額外依賴)這意味著:同一套代碼,換掉類路徑下的日誌實現 JAR,行為自動適配。
JCL 依賴 TCCL (Thread Context ClassLoader) 掃描實現類,在以下環境極易出問題:
這是 SLF4J 取代 JCL 成為主流門面的核心原因——SLF4J 在編譯期靜態綁定,避免運行時掃描風險。
| 專案類型 | 推薦方案 | 理由 |
|---|---|---|
| 新專案 / Spring Boot | SLF4J + Logback 或 SLF4J + Log4j2 | 編譯期綁定、效能最佳、功能最豐富、生態主流 |
| 維護舊 Log4j 1.x 專案 | Log4j 原生 API 或遷移至 SLF4J | Log4j 1.x 已停止維護,有安全風險 |
| 框架/庫開發 | SLF4J API | 零依賴、使用者自行選擇底層實現 |
| 極簡/零依賴專案 | JUL (java.util.logging) 或 SimpleLog | 無第三方 JAR,JCL 最後退回 SimpleLog |
Logger.getLogger() 和 LogFactory.getLog(),全面改用 org.slf4j.LoggerFactory.getLogger()log4j-over-slf4j、jcl-over-slf4j、jul-to-slf4j 將舊 API 重定向至 SLF4Jlogback-classic 或 log4j-slf4j-impl 作為最終實現logback-spring.xml 或 log4j2.xml 一份配置理解兩者本質差異,能幫助你在技術債重構、框架選型、疑難雜症排查時做出架構級決策。