Spring5.2.x-02-日誌體系
阿新 • • 發佈:2022-01-08
現象
- Spring體系中, 如果log是由spring-jcl搞出來的, 那麼log4j的配置會覆蓋logback;即使有logback與slf4j的繫結器, 也會優先使用log4j; 而其他, 如mybatis裡的日誌, 還是用自己的獨立的log元件來列印
- Spring-boot 預設使用logback, 日誌技術是統一的, 所有的是用一致的log元件
問題
- Spring的日誌體系為什麼與mybatis不互通
- Spring-boot為什麼可以讓日誌技術統一
java日誌分類
實現類框架
- JUL: java自帶log框架
- Log4j/Log4j2/LogBack: 第三方日誌記錄框架
門面框架
- JCL: 面向Log介面程式設計, 缺點是不更新、無法解決歷史硬編碼的log、log元件的選擇範圍是硬編碼於程式碼中
- Slf4j: 通過 Adapter 和 Bridge, 解決了歷史硬編碼的log不統一; 通過繫結器, 解決log元件的範圍自行配置
Spring-JCL
spring4.x用的是apache的jcl, 5.x之後用的是自己module的spring-jcl, 因為原來的jcl沒有繼續維護, spring-jcl自行維護了
spring-jcl只要看到log4j2, 就會啟用, 詳見以下程式碼片段
private static final String LOG4J_SPI = "org.apache.logging.log4j.spi.ExtendedLogger"; private static final String LOG4J_SLF4J_PROVIDER = "org.apache.logging.slf4j.SLF4JProvider"; private static final String SLF4J_SPI = "org.slf4j.spi.LocationAwareLogger"; private static final String SLF4J_API = "org.slf4j.Logger"; // 只要有 log4j if (isPresent(LOG4J_SPI)) { // 有橋接器 && 有slf4j, 才啟用 slf4j if (isPresent(LOG4J_SLF4J_PROVIDER) && isPresent(SLF4J_SPI)) { // log4j-to-slf4j bridge -> we'll rather go with the SLF4J SPI; // however, we still prefer Log4j over the plain SLF4J API since // the latter does not have location awareness support. logApi = LogApi.SLF4J_LAL; } else { // Use Log4j 2.x directly, including location awareness support logApi = LogApi.LOG4J; } } else if (isPresent(SLF4J_SPI)) { // Full SLF4J SPI including location awareness support logApi = LogApi.SLF4J_LAL; } else if (isPresent(SLF4J_API)) { // Minimal SLF4J API without location awareness support logApi = LogApi.SLF4J; } else { // java.util.logging as default logApi = LogApi.JUL; }
基本原理, 就是看能不能用反射找到對應的類, 找不到說明沒有執行環境沒有這個類, catch住為false即可
導致spring內部的log和外部其他的log不一定統一, 可能會出現Spring裡面是log4j2, Tomcat又是 jul, 不能統一配置
因此要加一個log4j-to-slf4j的橋接器(Spring-boot-web預設配置了橋接器, 日誌能統一為logback)
從日誌框架轉向SLF4J 橋接器
橋接器的包結構和需要橋接的日誌框架是一樣的, 類也是一樣的, 這樣編譯就不會報錯
應該用了代理, 不知道細節是怎麼實現的...
- jul-to-slf4j:jdk-logging到slf4j的橋樑
- log4j-over-slf4j:log4j1到slf4j的橋樑
- jcl-over-slf4j:commons-logging到slf4j的橋樑
從SLF4J轉向具體的日誌框架 繫結器
- slf4j-jdk14:slf4j到jdk-logging的橋樑
- slf4j-log4j12:slf4j到log4j1的橋樑
- log4j-slf4j-impl:slf4j到log4j2的橋樑
- logback-classic:slf4j到logback的橋樑
- slf4j-jcl:slf4j到commons-logging的橋樑