SLF4J(Simple logging Facade for Java)是一个日志框架的适配器。
如果一个项目已经使用了log4j,而你加载了Apache Active MQ——它依赖于于另外一个日志类库logback,那么你就需要把logback也加载进来。但如果Apache Active MQ使用了SLF4J,你可以继续使用log4j,而无需加载和维护一个新的日志框架。或者添加XXX-over-slf4j.jar可以将xxx的日志输出转向到slf4j,然后slf4j将日志交由真正的日志实现框架来输出

几个jar提一下:
jcl-over-slf4j 将Commons Logging API输出转向到slf4j输出。
log4j-1.2-api 将log4j适配到log4j2,从而程序不用修改。
log4j-jcl 将Commons Logging API输出转向到log4j2输出。


Slf4j启动

关键在于slf4j-api-xxx.jar中org.slf4j.LoggerFactory:

  // org/slf4j/impl/StaticLoggerBinder.class为log4j-slf4j-impl-xxxjar中的类,所以用字符串声明,避免具体依赖。
  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 {
//一般就是AppClassLoader
      ClassLoader loggerFactoryClassLoader = LoggerFactory.class
              .getClassLoader();
      Enumeration<URL> paths;
     //每一种类加载器加载指定的*.class文件会得到不同的Class,这里必须要保证LoggerFactory的类加载器与StaticLoggerBinder的类加载是相同的。
//ClassLoader.getSystemResources方法会调getSystemClassLoader()即启动当前application的classloader,一般就是AppClassLoader,若返回为空,则调getBootstrapResources()。 
//若存在多个日志框架,则类加载的URL有多个,所以是Enumeration<URL>
      if (loggerFactoryClassLoader == null) {//LoggerFactory为Bootstrap Loader载入。
        paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
      } else {
        paths = loggerFactoryClassLoader
                .getResources(STATIC_LOGGER_BINDER_PATH);
      }
      while (paths.hasMoreElements()) {
        URL path = (URL) paths.nextElement();
        staticLoggerBinderPathSet.add(path);
      }
    } catch (IOException ioe) {
     ......
    }
    return staticLoggerBinderPathSet;
  }

LoggerFactory的bind()方法会调用findPossibleStaticLoggerBinderPathSet(),若返回Set的大小超过1,则警告。通过StaticLoggerBinder.getSingleton()完成初始化,即实例化具体的factory赋值给内部的ILoggerFactory,如 loggerFactory = new Log4jLoggerFactory();。
不同的日志框架有相应的不同的xxx-slf4j-impl.jar,不同的StaticLoggerBinder.class决定了slf4j使用哪种日志框架。


重构地球
68 声望4 粉丝

rust-zero


« 上一篇
JDK动态代理
下一篇 »
Optional