slf4j

后续要做个日志相关的东西,先笔记一下。

slf4j是日志框架的一个门面端,背后实现者有log4j,logback等等。

如何实现这个门面的呢?

一般我们使用的代码如下:

private static final Logger logger = LoggerFactory.getLogger(JSPCashierController.class);

slf4j 的LoggerFactory具体实现了门面模式中对接各种实现的事情。

public static Logger getLogger(Class<?> clazz) {
        Logger logger = getLogger(clazz.getName());
        if (DETECT_LOGGER_NAME_MISMATCH) {
            Class<?> autoComputedCallingClass = Util.getCallingClass();
            if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
                Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(),
                                autoComputedCallingClass.getName()));
                Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation");
            }
        }
        return logger;
    }

     public static Logger getLogger(String name) {
        ILoggerFactory iLoggerFactory = getILoggerFactory();
        return iLoggerFactory.getLogger(name);
    }

getILoggerFactory方法:

public static ILoggerFactory getILoggerFactory() {
        if (INITIALIZATION_STATE == UNINITIALIZED) {
          // 防线程并发
            synchronized (LoggerFactory.class) {
                if (INITIALIZATION_STATE == UNINITIALIZED) {
                    INITIALIZATION_STATE = ONGOING_INITIALIZATION;
                    performInitialization();
                }
            }
        }
        switch (INITIALIZATION_STATE) {
        case SUCCESSFUL_INITIALIZATION:
            return StaticLoggerBinder.getSingleton().getLoggerFactory();
        case NOP_FALLBACK_INITIALIZATION:
            return NOP_FALLBACK_FACTORY;
        case FAILED_INITIALIZATION:
            throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
        case ONGOING_INITIALIZATION:
            // support re-entrant behavior.
            // See also http://jira.qos.ch/browse/SLF4J-97
            return SUBST_FACTORY;
        }
        throw new IllegalStateException("Unreachable code");
    }

上面,注意到一个细节,就是在getILoggerFactory是做了线程安全操作的,我看的版本是1.7.21。而在1.7.7的版本上的代码如下:是没有做线程安全的的事情的。

不过我也不知道啥原因,不深究了 哈哈。

public static ILoggerFactory getILoggerFactory() {
    if (INITIALIZATION_STATE == UNINITIALIZED) {
      INITIALIZATION_STATE = ONGOING_INITIALIZATION;
      performInitialization();
    }
    switch (INITIALIZATION_STATE) {
      case SUCCESSFUL_INITIALIZATION:
        return StaticLoggerBinder.getSingleton().getLoggerFactory();
      case NOP_FALLBACK_INITIALIZATION:
        return NOP_FALLBACK_FACTORY;
      case FAILED_INITIALIZATION:
        throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
      case ONGOING_INITIALIZATION:
        // support re-entrant behavior.
        // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
        return TEMP_FACTORY;
    }
    throw new IllegalStateException("Unreachable code");
  }

结下来看performInitialization方法:

private final static void performInitialization() {
  bind();
  if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {
    versionSanityCheck();
  }
}

到了bind方法了,具体绑定哪一个实现应该就在这里决定了:

private final static void bind() {
    try {
      Set<URL> staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
      reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
      // the next line does the binding
      // 这里绑定的实例抽象,我们获取或设置所有logger相关信息都是通过它实现
      StaticLoggerBinder.getSingleton();
      INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
      reportActualBinding(staticLoggerBinderPathSet);
      fixSubstitutedLoggers();
    } catch (NoClassDefFoundError ncde) {
      String msg = ncde.getMessage();
      if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
        INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
        Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
        Util.report("Defaulting to no-operation (NOP) logger implementation");
        Util.report("See " + NO_STATICLOGGERBINDER_URL
                + " for further details.");
      } else {
        failedBinding(ncde);
        throw ncde;
      }
    } catch (java.lang.NoSuchMethodError nsme) {
      String msg = nsme.getMessage();
      if (msg != null && msg.indexOf("org.slf4j.impl.StaticLoggerBinder.getSingleton()") != -1) {
        INITIALIZATION_STATE = FAILED_INITIALIZATION;
        Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
        Util.report("Your binding is version 1.5.5 or earlier.");
        Util.report("Upgrade your binding to version 1.6.x.");
      }
      throw nsme;
    } catch (Exception e) {
      failedBinding(e);
      throw new IllegalStateException("Unexpected initialization failure", e);
    }
  }

findPossibleStaticLoggerBinderPathSet方法:

// 就是在classpath里找这个class,所以那些实现者比如log4j,logback,包里必然有这个路径下的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 = (URL) paths.nextElement();
      staticLoggerBinderPathSet.add(path);
    }
  } catch (IOException ioe) {
    Util.report("Error getting resources from path", ioe);
  }
  return staticLoggerBinderPathSet;
}
时间: 2024-10-13 20:19:50

slf4j的相关文章

log4j与commons-logging,slf4j的关系

1.slf4j  他只提供一个核心slf4j api(就是slf4j-api.jar包),这个包只有日志的接口,并没有实现,所以如果要使用就得再给它提供一个实现了些接口的日志包,比 如:log4j,common logging,jdk log日志实现包等,但是这些日志实现又不能通过接口直接调用,实现上他们根本就和slf4j-api不一致,因此slf4j又增加了一层来转换各日志实 现包的使用,当然slf4j-simple除外. slf4j+log4j组合使用模式:1. slf4j-api-1.5.

Atitit.日志系统slf4j的使用

SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/C:/0workspace/AtiPlatf_cms/lib_slf1.7.5/slf4j-nop-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/C:/0workspace/AtiPlatf_cms

使用 slf4j

实际上我对日志服务的要求不高,大多数情况下能够打印信息就可以了,例如 ActionScript 的 trace(); 这么的基本的函数我就觉得足够了,包括在网页调试中 alert() 大法更是屡试不爽.好了,来到 Java 世界,仍沿用这一思想,所以 sysout 快捷键下生成的 System.out/err.println("xxx"): 也没觉得有什么障碍.但长久以来 sysout 总感觉不妥,尤其运维的兄弟看到你这一堆打印的东东,而他又不是十分明白那是啥就有意见了,可想而知更严重

踩坑记(1)——使用slf4j+logback记录日志

jar包版本: <spring.version>3.1.0.RELEASE</spring.version> <slf4j.version>1.7.25</slf4j.version> <logback.version>1.2.3</logback.version> <logback.ext.version>0.1.1</logback.ext.version> commons-logging:scope为pr

eclipse安装maven插件-解决requires ‘bundle org.slf4j.api 1.6.2′

eclipse安装maven插件-解决requires 'bundle org.slf4j.api 1.6.2′ [转载]http://robin.sh/html/1526_eclipse-maven.html 给eclipse安装maven插件,网上教程已经很多,不在累述.关键是安装过程中报错:requires 'bundle org.slf4j.api 1.6.2' but it could not be found. 这个错误很难搞,网上提供的解决方案绝大部分都不起作用.可能跟eclips

使用SLF4J和LOGBACK (一 : 基本使用)

1.SLF4J是什么? slf4j是一个日志门面,它不是具体的日志实现框架,而是提供了通用的日志接口,按个人理解来说,是通过接口实现多态,来满足应用在不同日志框架间切换的需求. 例如在程序中我们需要记录日志,使用SLF4J提供的接口来调用: Logger logger = LoggerFactory.getLogger(Class.class); logger.info(); 上边两行代码中的Logger和LoggerFactory对象均来自SLF4J包中. 具体的日志实现框架,我们可以选择LO

slf4j+logback搭建超实用的日志管理模块

文章转自http://www.2cto.com/kf/201702/536097.html slf4j+logback搭建超实用的日志管理模块(对日志有编号管理):日志功能在服务器端再常见不过了,我们非常有必要记录下发生在服务器上的活动,这些日志将用于debug.统计等各种用途. slf4j+logback这种实现方式是很常见的,好处自然是方便!.在这篇文章中,你将看到如何使用logback搭建你自己的日志组件并将日志输出到文件.如何查看这些文件.如何为每个线程上的访问分配独有的一个日志id.

SLF4J: Failed to load class &quot;org.slf4j.impl.StaticLoggerBinder&quot;.

调试Mina程序出现如下错误: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: Defaulting to no-operation (NOP) logger implementationSLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. 下载相应的slf4j的jar包,在slf4

Failed to load class &quot;org.slf4j.impl.StaticLoggerBinder&quot;

调试程序出现如下错误: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: Defaulting to no-operation (NOP) logger implementationSLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. 下载相应的slf4j的jar包,在slf4j官网下

实现jul 日志重定向到 slf4j

需求背景 jul 指的是java.util.logging,是 java 内置的日志模块,目前流行的Java日志组件还包括 jcl(common-logging).slf4j/log4j/logback 等等 不同日志框架的定位和特性都存在差异,如 jcl.slf4j 提供的是日志门面(api)定义,log4j.logback则侧重于实现. 通常一个团队会采用统一的日志组件,slf4j 目前的受欢迎程度较高,其在易用性.可移植性方面都优于jul: 然而项目中采用的一些开源组件可能直接采用了jul