一、概述

log4j→jul→jcl→slf4j之后就开始百花齐放【slf4j适配兼容新老用户】

1.1、log4j阶段  

  在JDK出现后,到JDK1.4之前,常用的日志框架是apache的log4j。

1.2、jul阶段

  在JDK1.4后,sun公司增加了一个包为java.util.logging,简称为jul,用以对抗log4j。

1.3、jcl阶段【commons-logging】

  开源项目都使用的是 log4j,log4j 已经成了事实上的标准,但由于又有一部分开发者在使用 sun logger,既jul,因此 apache 又推出 Apache Commons Logging,使得我们不必关注我们正在使用何种日志工具。

  Apache Commons Logging(JCL),之前叫Jakarta Commons Logging,简称JCL,是Apache提供的一个通用日志API,可以让应用程序不再依赖于具体的日志实现工具。Apache commons-logging是JCL的标准实现。

  commons-logging包中对其它一些日志工具,包括Log4J、Avalon LogKit、JUL等,进行了简单的包装,可以让应用程序在运行时,直接将JCL API打点的日志适配到对应的日志实现工具中。

  JCL通过动态查找的机制,在程序运行时自动找出实际使用的日志库。

    

  JCL为每一种日志实现采用了一个适配器,具体采用哪个、是动态的根据指定顺序查找classPath是否存在相应日志的实现。如果JCL运行时没找到任何一种第三方的日志实现,则就用jdk14自带的java.util.logging(JUL)。假如你的maven工程pom.xml里加入了log4j的依赖,运行时JCL找到即可动态绑定。

  Spring 的日志就是采用JCL,解决了应用程序和框架日志不统一的问题。动态去寻找(应用程序配置的)日志体系的实现。

  但JCL方式也有不足,不能把所有日志的实现都包含。具体可以看commons-logging框架的LoggerFactory和LoggerFactoryImpl,里面硬编码了数组,不包含log4j2和logback的最新实现。

  org.apache.commons.logging.impl.LogFactoryImpl见下图:

    
  通过看JCL的源码,jcl为每一种日志实现采用了一个适配器,具体采用哪个、是动态的根 据指定顺序查找classPath是否存在相应的实现,查找顺序就是数组元素的顺序。如果一个应用当中有多个classLoader。比如OSGI规定了每个模块都有其独立的ClassLoader。这种机制保证了插件互相独立,同时也限制了JCL在OSGi中的正常使用。

  其实就是:jcl默认的配置:如果能找到Log4j 则默认使用log4j 实现,如果没有则使用jul(jdk自带的) 实现,再没有则使用jcl内部提供的SimpleLog 实现。

  代码使用

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
\\省略
Log log =LogFactory.getLog(Test.class);
log.trace('trace');
\\省略

  至于这个Log具体的实现类,JCL会在ClassLoader中进行查找。这么做,有三个缺点,缺点一是效率较低,二是容易引发混乱,三是在使用了自定义ClassLoader的程序中,使用JCL会引发内存泄露。

1.4、slf4j阶段【slf4j-api】

  SLF4J 全称 Simple Logging Facade for Java(简单日志门面)。与JCL类似,本身不替供日志具体实现,只对外提供接口或门面。因此它不是具体的日志解决方案,而是通过Facade Pattern门面模式对外提供一些Java Logging API。这些对外提供的核心API其实就是一些接口以及一个LoggerFactory的工厂类。
  在使用SLF4J的时候,不需要在代码中或配置文件中指定你打算使用哪个具体的日志系统,可以在部署的时候不修改任何配置即可接入一种日志实现方案,在编译时静态绑定想用的Log库。
  按照官方的说法,SLF4J是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。作者创建SLF4J的目的是为了替代Apache Commons Logging。即使以后又出现更新的其他日志组件,也能完全适应。

  log4j的作者觉得jcl不好用,自己又写了一个新的接口api,那么就是slf4j。关于slf4j的集成图如下所示

    

  如图所示,应用调了sl4j-api,即日志门面接口。日志门面接口本身通常并没有实际的日志输出能力,它底层还是需要去调用具体的日志框架API的,也就是实际上它需要跟具体的日志框架结合使用。由于具体日志框架比较多,而且互相也大都不兼容,日志门面接口要想实现与任意日志框架结合可能需要对应的桥接器,上图红框中的组件即是对应的各种桥接器!

  使用SLF4J时,如果你需要使用某一种日志实现,那么你选择相对应的SLF4J的桥接包即可。比如使用log4j日志组件,就选slf4j-log4j12桥接包,业务中就可以使用log4j进行底层日志输出。

  SLF4J提供的桥接包:
    • slfj-log4j12.jar (表示桥接 log4j)
    • slf4j-jdk14.jar(表示桥接jdk Looging)
    • sIf4j-jcl.jar(表示桥接 jcl)
    • log4j-slf4j-impl(表示桥接log4j2)
    • logback-classic(表示桥接 logback)

  logback是slf4j-api的天然实现,不需要桥接包就可以使用。与commons loging(JCL)不同的是其采用在classPath加入桥接jar包来表示具体采用哪种实现(静态绑定)

  我们在代码中需要写日志,变成下面这么写

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//省略
Logger logger = LoggerFactory.getLogger(Test.class);
// 省略
logger.info("info");

  在代码中,并不会出现具体日志框架的api。程序根据classpath中的桥接器类型,和日志框架类型,判断出logger.info应该以什么框架输出!注意了,如果classpath中不小心引了两个桥接器,那会直接报错的!

  因此,在阿里的开发手册上才有这么一条

强制:应用中不可直接使用日志系统(log4j、logback)中的 API ,而应依赖使用日志框架 SLF4J 中的 API 。使用门面模式的日志框架,有利于维护和各个类的日志处理方式的统一。

二、日志乱象的归纳与统一

2.1、spring日志与log4j2等非jcl实现结合【jcl-over-slfj.jar】

  Spring采用的JCL【log4j、jul、simpleLog】中不包含log4j2(LoggerFactoryImpl源码中定义的数组中不包含log4j2),运行时,JCL从数组顺序寻找日志的实现,如果没有引入其他实现,最终则会用JUL打印日志,

    

  这时会出现的问题,Spring 打印日志方式和应用程序打印日志不统一,错误排除时比较困难。而且应用程序和Spring框架,日志不统一,太乱了,还得搞2份日志配置文件。

  为了让Spring和我们的应用程序,采用统一的log4j2 日志体系,需要加入适配器。改善上面应用程序和框架日志不统一的问题(加入适配器后):

    

  中间这个适配器:其实就是jcl-over-slfj.jar(jcl适配slf4j),加入下面的依赖即可,再去除commons-logging。

001-log-log体系-log4j、jul、jcl、slf4j,日志乱象的归纳与统一的更多相关文章

  1. Log4j,Log4j2,logback,slf4j日志学习

    日志学习笔记 Log4j Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.数据库等:我们也可以控制每一条日志的输出格式:通过定义每一条 ...

  2. Log4j,Log4j2,logback,slf4j日志学习(转)

    日志学习笔记Log4jLog4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.数据库等:我们也可以控制每一条日志的输出格式:通过定义每一条日志 ...

  3. Java 日志框架概述(slf4j / log4j / JUL / Common-logging(JCL) / logback)

    一.简介 JAVA日志在初期可能官方并没有提供很好且实用的规范,导致各公司或OSS作者选择自行造轮子,这也导致了目前初学者觉得市面上 Java 日志库繁杂的局面. 现在市面流行以 slf4j(Simp ...

  4. 常见java日志系统的搭配详解:关于slf4j log4j log4j2 logback jul jcl commons-logging jdk-logging

    先看一张图: 是不是有点晕, 晕就对了.这个仅仅是 slf4j 的情况,实际上, 我们不仅要接触到 slf4j ,有时候还会接触其他的日志系统.且看下文分解. 1 直接使用各个日志系统 1.1 直接使 ...

  5. SLF4J其实只是一个门面服务而已,他并不是真正的日志框架,真正的日志的输出相关的实现还是要依赖Log4j、logback等日志框架的。

    小结: 1.加层: 每一种日志框架都有自己单独的API,要使用对应的框架就要使用其对应的API,这就大大的增加应用程序代码对于日志框架的耦合性. 为了解决这个问题,就是在日志框架和应用程序之间架设一个 ...

  6. log4j与commons-logging slf4j的关系

    1. slf4j     他只提供一个核心slf4j api(就是slf4j-api.jar包),这个包只有日志的接口并没有实现     所以如果要使用就得再给它提供一个实现了些接口的日志包,     ...

  7. 为什么使用 SLF4J 而不是 Log4J 来做 Java 日志

    转自:为什么使用 SLF4J 而不是 Log4J 来做 Java 日志 英文原文:Why use SLF4J over Log4J for logging in Java 每个Java开发人员都知道日 ...

  8. Java日志体系(四)slf4j

    1.1 简介 与commons-logging相同,slf4j也是一个通用的日志接口,在程序中与其他日志框架结合使用,并对外提供服务. Simple Logging Facade for Java简称 ...

  9. /var/log目录下的20个Linux日志文件功能详解

    如果愿意在Linux环境方面花费些时间,首先就应该知道日志文件的所在位置以及它们包含的内容.在系统运行正常的情况下学习了解这些不同的日志文件有助于你在遇到紧急情况时从容找出问题并加以解决. 以下介绍的 ...

随机推荐

  1. JAVA处理数字与中文数字互转(最大处理数字不超过万兆即:9999999999999999.9999)

    package practice; import java.util.Arrays; /** * 数字与中文数字互转(最大处理数字不超过万兆即:9999999999999999.9999) * @au ...

  2. IDEA 导入jar包

    项IDEA的项目中导入下载好的jar包: 在intelij IDEA 中,点击File-Project Structure,出现界面的左侧点击Modules,然后点击“+”. 然后找到你要导入的jar ...

  3. 【Mysql MHA】CentOS7.6+Mysql8.0.16 入坑

    1.防火墙 firewall-cmd --add-port=/tcp --permanent firewall-cmd --reload 2.SELINUX sed -i 's/SELINUX=enf ...

  4. 对于vector中高效删除中间元素的技巧

    众所周知,vector是连续存储空间,只提供高效的尾部删除方法pop_back() ,在中间删除的效率很低,那么如果大家想快速删除中间元素该如何实现? 话不多说,看代码: //移除vector元素,最 ...

  5. Oracle不足补零函数

    ,') from dual ,') from dual ,') from dual ,') from dual ,') from dual

  6. 我是如何理解Android的Handler模型_1

    Handler Message类似于旧时的电话系统,对应关系如下: 电话局->Handler 电话机->Message 接线员->handlerMessage 接线员的工作-> ...

  7. 2019牛客多校第五场 generator 1——广义斐波那契循环节&&矩阵快速幂

    理论部分 二次剩余 在数论中,整数 $X$ 对整数 $p$ 的二次剩余是指 $X^2$ 除以 $p$ 的余数. 当存在某个 $X$,使得式子 $X^2 \equiv d(mod \ p)$ 成立时,称 ...

  8. Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 1) 题解

    A. Toy Train 时间限制:2 seconds 内存限制:256 megabytes 题意 有编号111~n(n≤5000)n(n\le 5000)n(n≤5000)的车站顺时针呈环排列,有m ...

  9. angularjs 动态计算平均值

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. 001_C#我的第一个串口上位机软件

    (一)首先感谢杜洋工作室 < 入门 C#设计 >带来的视频教学 (二)本次设计从会单片机但是又不会上位机又想搞简单上位机的人群角度提供教程 (三)本次教程的目的是制作普通的串口软件,从而实 ...