徹底搞明白爲什麼日誌框架依賴衝突了

項目啓動報錯如下:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
qdc is restarting
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=1024M; support was removed in 8.0
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/xxx/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/xxx/lib/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
log4j:WARN No appenders could be found for logger (com.qihoo.bigdata.foundation.spring.startup.OnStartup).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Exception in thread "main" java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.impl.Log4jLoggerFactory loaded from file:/xxx/lib/slf4j-log4j12-1.7.25.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.impl.Log4jLoggerFactory
        at org.springframework.util.Assert.instanceCheckFailed(Assert.java:637)
        at org.springframework.util.Assert.isInstanceOf(Assert.java:537)
        at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:286)
        at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:102)
        at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:191)
        at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:170)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
        at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:68)
        at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:48)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1258)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246)

系統發現了多個日誌實現,最終因爲張冠李戴而發生了異常。
這種很常見,而且在建項目和後期開發過程,很容易無意中引入的jar間接帶入另一個日誌實現,從而引起日誌框架的衝突。

爲什麼會衝突呢?

筆者通過maven helper這個IDEA插件來分析依賴:
在這裏插入圖片描述
如上圖所示,在依賴中發現了兩個日誌實現框架,兩個橋接器jar包。筆者用一個更加直觀的圖來展示發生了什麼
在這裏插入圖片描述
目前依賴爲log4j-api提供了兩種日誌實現:第一種很直接是logback,第二種經過混亂的橋接,兜兜轉轉最終找到了log4j。

怎麼解決呢?

排除掉一種實現即可。
這裏面有講究,日誌接口更傾向於使用更加通用的框架slf4j-api,而不是log4j-api。
因爲slf4j能適配幾乎所有的日誌實現,比如log4j、jul、logback等等
在這裏插入圖片描述
而log4j-api僅僅是log4j這個日誌框架的門面,通用性不好。

方案一(最優)

  1. 先將log4j-api換成slf4j-api
  2. 排除log4j、slf4j-logj12

使用slf4j-api門面,實現選用logback,後期可以任意切換實現

方案二

  1. 排除logback-xx
  2. 排除log4j-to-slf4j、slf4j-log4j12

使用log4j-api門面,使用log4j作爲固定實現。通用性不好,綁死了log4j日誌框架。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章