1. 程式人生 > >slf4j作用及其實現原理

slf4j作用及其實現原理

logger 解決 OS smo tac except prop body 打印

為什麽要使用slf4j

現實場景:

我們自己的系統中使用了logback這個日誌系統

我們的系統使用了A.jar,A.jar中使用的日誌系統為log4j

我們的系統又使用了B.jar,B.jar中使用的日誌系統為slf4j-simple

這樣,我們的系統就不得不同時支持並維護logback、log4j、slf4j-simple三種日誌框架,非常不便。

解決這個問題的方式就是引入一個適配層,由適配層決定使用哪一種日誌系統,而調用端只需要做的事情就是打印日誌而不需要關心如何打印日誌,slf4j或者commons-logging就是這種適配層。

從上面的描述,我們清楚地知道一點:slf4j只是一個日誌標準,並不是日誌系統的具體實現

理解這句話非常重要,slf4j只做兩件事情

  • 提供日誌接口
  • 提供獲取具體日誌對象的方法

slf4j-simple、logback-classic都是slf4j的具體實現,log4j並不直接實現slf4j,但是有專門的一層橋接slf4j-log4j12來實現slf4j。

slf4j實現原理

slf4j的用法就是一句"Logger logger = LoggerFactory.getLogger(Object.class);"

可見這裏就是通過LoggerFactory去拿slf4j提供的一個Logger接口的具體實現而已。getLogger的時候會去classpath下找STATIC_LOGGER_BINDER_PATH,即所有slf4j的實現,在提供的jar包路徑下,一定是有"org/slf4j/impl/StaticLoggerBinder.class"存在的。

    private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";

    private static Set<URL> findPossibleStaticLoggerBinderPathSet() {
        // use Set instead of list in order to deal with bug #138
        // LinkedHashSet appropriate here because it preserves insertion order during iteration
Set<URL> staticLoggerBinderPathSet = new LinkedHashSet<URL>(); try { ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader(); Enumeration<URL> paths; if (loggerFactoryClassLoader == null) { paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH); } else { paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH); } while (paths.hasMoreElements()) { URL path = paths.nextElement(); staticLoggerBinderPathSet.add(path); } } catch (IOException ioe) { Util.report("Error getting resources from path", ioe); } return staticLoggerBinderPathSet; }

我們不能避免在系統中同時引入多個slf4j的實現,所以接收的地方是一個Set。

同時存在多個"org/slf4j/impl/StaticLoggerBinder.class"怎麽辦?

首先確定的是這不會導致啟動報錯只會打印warnning,其次在這種情況下編譯期間,編譯器會選擇其中一個StaticLoggerBinder.class進行綁定,sfl4j也在reportActualBinding方法中報告了綁定的是哪個日誌框架。

StaticLoggerBinder就比較簡單了,不同的StaticLoggerBinder其getLoggerFactory實現不同,拿到ILoggerFactory之後調用一下getLogger即拿到了具體的Logger,可以使用Logger進行日誌輸出。

slf4j作用及其實現原理