`

[转]JCL-Over-SLF4J+SLF4J+Logback 使用方式

阅读更多

我们前面已经讲过了 SLF4J 的两种用法:SLF4J+Log4J  和 SLF4J+Logback,那是在比较理想的情况下,所用组件只使用了 SLF4J 这一种统一日志框架的时候。可是 JCL 一直影响深远,SLF4J 渐入佳境的时个,在你的项目中很可能所用的组件,它们分别用了 JCL 和 SLF4J 两种组件。比如说在项目中用了 Hibernate 3.5 和 Struts,或其他 Apache 的一些开源组件,你大约也不想用了 SLF4J 的组件日志信息输出到 A 处,用了 JCL 的组件日志输出到 B 处,那你自己写的代码中的日志信息该往哪儿写呢?

中国人一直都愿追求大一统,不喜欢城邦制的便于分而治之。但说到日志输出还是得统一到单一通道中来,一方面多个通道浪费资源,另方面也便于配置和管理。那么既然 SLF4J 是趋势,当 SLF4J 和 JCL 被丢到一个坛子里,首先会让 SLF4J 为主,JCL 为辅,也就是要把 JCL 桥接到 SLF4J 上来,通过 SLF4J 统一输出日志信息。于是也就是这篇要介绍的 SLF4J 使用模式:JCL-Over-SLF4J+SLF4J。

从前面对 SLF4J 的认识可知,即使把 JCL 转嫁到 SLF4J,还是无法输出日志,还需要一种日志实现,下层该用 Log4J 还得用 Log4J,想用 Logback 还是要用 Logback。所以到了 SLF4J 后还得往下走,也就是前面那两条路 SLF4J+Log4J 和 SLF4J+Logback,本篇使用 SLF4J 的模式具体就要分为:

JCL-Over-SLF4J+SLF4J+Log4J 和 JCL-Over-SLF4J+SLF4J+Logback,这两种实现方式差不多。只是分别用的 jar 包和配置文件不同,SLF4J+Log4J 和 SLF4J+Logback 原来要哪些文件现在还是需要那些文件,只是都要加上 jcl-over-slf4j-1.5.11.jar 包。这里说明 JCL-Over-SLF4J+SLF4J+Logback 的方式。

需要的配置文件和组件包,下面四个 jar 文件和一个 xml文件都是要放在项目的 ClassPath 上。

1. slf4j-api-1.5.11.jar
2. logback-core-0.9.20.jar
3. logback-classic-0.9.20.jar
4. logback.xml 或 logback-test.xml
5. jcl-over-slf4j-1.5.11.jar

第 1 和第 5 个包在 http://www.slf4j.org/download.html 处下载,第二第三个包在 http://logback.qos.ch/download.html 下载,可能包文件名中的版本号有些差异。

下面是一个最简单的 logback.xml 文件内容

01
02
03
04
05
06
07
08
09
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
      <encoder charset="GBK">
          <pattern>[Consociate] %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
      </encoder>
  </appender
 
  <root level="DEBUG">
    <appender-ref ref="stdout" />
  </root>
</configuration>

为了看看效果,我们在输入的 pattern 中加入了 [Consociate],来检验是否统一到单一的日志通道中去了。

使用 了 JCL 和 SLF4J  的代码

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
package com.unmi;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
public class TestJCLOverSlf4j {
    //SLF4J 的 Logger
    private static final Logger logger = LoggerFactory.getLogger("From SLF4J");
 
    //JCL 的 Log
    private static final Log log = LogFactory.getLog("From JCL");
 
    //分别用上面的 logger 和 log 输出日志,从输出可以看到它们统一到一个通道中了
    public static void main(String[] args) {
        logger.info("Hello {}","From SLF4J");
        log.info("Hello From JCL");
    }
}

我们在上面代码中,既使用了 JCL 统一日志框架,也使用了 SLF4J 的统一日志框架。要注意一点,从 JCL 桥接过来的 log 不能输出参数化消息了。上面代码使用了 org.apache.commons.logging.Log,import org.apache.commons.logging.LogFactory,但你却用不着引入 commons-logging.jar 包。

执行上面的代码,看到输出:

[Consociate] 23:19:39.890 [main] INFO  From SLF4J - Hello From SLF4J
[Consociate] 23:19:39.921 [main] INFO  From JCL - Hello From JCL

很明显示 JCL 框架和 SLF4J 框架的日志输出都统一到了一个通道中来了,为什么呢? SLF4J 使用的是 Logback 输出的信息,这一点没问题的,而 JCL 是不认识 Logback 的,所以 JCL 框架的输出必然是绕道到 SLF4J,最后也是由 Logback 输出的。

实现分析:

我们打开 jcl-over-slf4j-1.5.11.jar,看到里面有两个包 org.apache.commons.logging 和 org.apache.commons.logging.impl,并有相应的类,这就是为什么,虽然在代码中有:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

却不用把 commons-logging.jar 包引入到类路径上的原因。

再深入下 jcl-over-slf4j-1.5.11.jar,看到其中还有个文件 /META-INF/services/org.apache.commons.logging.LogFactory,内容为:

org.apache.commons.logging.impl.SLF4JLogFactory

# Axis gets at JCL through its own mechanism as defined by Commons Discovery, which
# in turn follows the instructions found at:
http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service Provider

JCL 运行时使用了 SLF4JLogFactory,从而完成了 JCL 的日志实现委托给了 SLF4J,再由 SLF4J 进一步完成具体的日志输出。

采用 JCL-Over-SLF4J+SLF4J+Log4J 使用模式也是相似的,这里就不详述了。总结下就是 JCL 把 SLF4J 当作它的日志实现。

再来想象个问题:如果我们把这两个包 jcl-over-slf4j-1.5.11.jar 和 slf4j-jcl-1.5.11.jar 都放到 ClassPath 下会有什么情况呢?JCL 代理给 SLF4J,SLF4J 又绑定到 JCL,对了,死循环,StackOverFlow 错误:

SLF4J: Detected both jcl-over-slf4j.jar AND slf4j-jcl.jar on the class path, preempting StackOverflowError.
SLF4J: See also 
http://www.slf4j.org/codes.html#jclDelegationLoop for more details.
java.lang.ExceptionInInitializerError
at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:82)
at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:51)
at org.slf4j.LoggerFactory.getSingleton(LoggerFactory.java:230)
at org.slf4j.LoggerFactory.bind(LoggerFactory.java:121)
at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:112)
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:275)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:248)
at com.unmi.TestJCLOverSlf4j.<clinit>(TestJCLOverSlf4j.java:10)
Caused by: java.lang.IllegalStateException: Detected both jcl-over-slf4j.jar AND slf4j-jcl.jar on the class path, preempting StackOverflowError. See also
http://www.slf4j.org/codes.html#jclDelegationLoop for more details.
at org.slf4j.impl.JCLLoggerFactory.<clinit>(JCLLoggerFactory.java:64)
... 8 more
Exception in thread "main"

分享到:
评论

相关推荐

    slf4j-1.6.1+logback-0.9.24.rar

    jcl-over-slf4j-1.6.1.jar log4j-1.2.8.jar logback-access-0.9.24.jar logback-classic-0.9.24.jar logback-core-0.9.24.jar servlet-api.jar slf4j-1.6.1+logback-0.9.24.rar slf4j-api-1.6.1.jar

    log4j-1.2.17.jar、logback-core-1.1.2.jar、slf4j-simple-1.7.12.jar等

    commons-logging-1.2.jar、log4j-1.2.17.jar、logback-classic-1.1.2.jar、logback-core-1.1.2.jar、slf4j-api-1.7.12.jar、slf4j-jcl-1.7.12.jar、slf4j-simple-1.7.12.jar

    log4j logback slf4j

    NULL 博文链接:https://tristan-s.iteye.com/blog/1966020

    基于Java日志平台的访问链路追踪实战(1.01G)

    ---10-slf4j与其他日志的配合与总结.mp4 ---11-log4j2的配置与日志发展历程总结.mp4 ---12-日志组件配置概述.mp4 ---13-jul配置文件与级别.mp4 ---14-jul打印级别与其他配置项.mp4 ---15-log4j配置文件与配置项.mp4 ...

    基于Java日志平台的访问链路追踪实战(1.34G)

    ---10-slf4j与其他日志的配合与总结.mp4 ---11-log4j2的配置与日志发展历程总结.mp4 ---12-日志组件配置概述.mp4 ---13-jul配置文件与级别.mp4 ---14-jul打印级别与其他配置项.mp4 ---15-log4j配置文件与配置项.mp4 ...

    快速了解常用日志技术(JCL、Slf4j、JUL、Log4j、Logback、Log4j2)-附件资源

    快速了解常用日志技术(JCL、Slf4j、JUL、Log4j、Logback、Log4j2)-附件资源

    考试系统源码java-org.ops4j.pax.logging:OSGi日志框架实现。支持SLF4J、LOG4J、JCL等

    SLF4J 或 Commons-Logging。 日志 API本身不做任何日志,而是需要特定的日志实现(和相关配置)和日志实现本身之间应该有区别。 与上述区别相匹配的日志 API(或Facades )包括: 日志实现始终提供自己的API,并且...

    日志框架总结JUL、Log4j、Log4j2、Logback以及门面技术

    日志框架与日志门面的区别 日志框架技术 JUL 使用 Log4j 组件 使用 Logback 由Log4j之父做的另一个开源项目,业界中称作logj后浪,一个可靠、同样且灵活的java日志框架。 Logback组件 ...SLF4j 使用

    开发用jar包合集

    jcl-over-slf4j-1.7.7.jar jcommander-1.12.jar jdom.jar jetty-6.1.25.jar jetty-annotations-6.1.25.jar jetty-naming-6.1.25.jar jetty-plus-6.1.25.jar jetty-util-6.1.25.jar jna-3.2.7.jar jna-...

    java日志框架视频教程

    视频详细讲解,需要的小伙伴自行网盘下载,链接见附件,... logback-access使用章节七:Log4j21. 快速入门2. 配置文件3. 异步日志4. 性能介绍章节八:SpringBoot使用日志1. springBoot日志设计2. springBoot日志使用

    java代码实例-日志规范史上最全java日志攻略(附教程)

    SLF4J "日志门面的使用 日志的绑定 日志的桥接 日志门面的原理" log-back "log-back的日志框架 log-back的配置 logback记录tomcat的访问日志" log4j2 "log4j2的日志框架 log4j2的配置 异步日志的使用" spring整合log...

    Java日志体系全解析:架构师必掌握的关键技术和最佳实践

    它不仅提供了一个更为简洁高效的日志门面,还通过各种适配器支持了众多日志实现,如log4j、logback等。SLF4J通过解耦日志API和具体实现,提高了程序的灵活性和可维护性。 Spring框架在其不同版本中使用了不同的日志...

    SpringBoot日记——日志框架篇.docx

    在项目的开发中,日志是必不可少的...而市面上常见的日志框架有很多,比如:JCL、SLF4J、Jboss-logging、jUL、log4j、log4j2、logback等等,我们该如何选择呢? 通常情况下,日志是由一个抽象层+实现层的组合来搭建的。

    谈谈你了解的springboot日志框架

    到现在为止呢,已经有很多日志可供选择了,而市面上常见的日志框架有很多,比如: JCL 、 SLF4J 、 Jboss-logging 、 jUL(Java Util Logging) 、 log4j 、 log4j2 、 logback 等等,我们该如何选择呢?

    Java日志框架

    眼下java应用日志收集都是採用日志框架(slf4j、apachecommonslogging)+日志系统(log4j、log4j2、LogBack、JUL等)的方式。日志框架:提供日志调用的接口,实际的日志输出托付给日志系统实现。JCL...

    sofa-common-tools:Sofa-common-tools是一个向其他SOFA库提供一些实用程序功能的库

    背景在日常开发中,Java日志记录通常包括选择日志外观(例如JCL和SLF4j)和日志实现(例如Log4j2和logback)。 假设您正在开发使用JAR的应用程序,该JAR利用log4j2进行日志记录。 在这种情况下,您不能选择log4j2...

    springboot-learn-jdbc.zip

    │ Maven__org_apache_logging_log4j_log4j_to_slf4j_2_12_1.xml │ Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_33.xml │ Maven__org_apache_tomcat_embed_tomcat_embed_el_9_0_33.xml │ Maven__...

    enterprise-spring-best-practices:企业Spring最佳实践

    企业Spring最佳实践 博客系列“ Enterprise Spring最佳实践”的代码伴侣站点 ...SLF4J和Logback配置 Apache Commons(又名Jakarta Commons / JCL) Java Util(又名JUL) System.out和System.err 资源

Global site tag (gtag.js) - Google Analytics