一、概述

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. sqlplus set相关设置

    Oracle里的set零零碎碎的,这里整理归纳一下 SQL> set timing on;          //设置显示“已用时间:XXXX” SQL> set autotrace on ...

  2. Centos7下安装Elasticsearch 5.6.6

    环境 因为elasticsearch是用java编写的,所以需要先安装JDK ES 5,安装需要 JDK 8 以上ES 6.5,安装需要 JDK 11 以上ES 7.2.1,内置了 JDK 12 安装 ...

  3. nginx 缓存区太小导致后台Connection reset by peer 报错

    问题概述:图片bit 64生成数据流太大,导致小程序分享弹窗的二维码图片生成失败 后台报错: 排查: Client------>nginx------->h5------>nginx ...

  4. java-集合处理数据的效率差异

    先给结论,ArrayList数组结构的,插入和删除耗时长,get(index)耗时短. LinkedList是链表结构的,插入和删除耗时短,get(index)耗时长. 常用的几种集合,ArrayLi ...

  5. Http 缓存剖析

    缓存一直是前端优化的主战场, 利用好缓存就成功了一半. 本篇从http请求和响应的头域入手, 让你对浏览器缓存有个整体的概念. 最终你会发现强缓存, 协商缓存 和 启发式缓存是如此的简单. 导读 浏览 ...

  6. Java并发包--线程池原理

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509954.html 线程池示例 在分析线程池之前,先看一个简单的线程池示例. 1 import jav ...

  7. 从 ES6 到 ES10 的新特性万字大总结

    以下文章来源于鱼头的Web海洋 ,作者陈大鱼头   鱼头的Web海洋 一个名为Web的海洋世界 (给前端大全加星标,提升前端技能) 作者:鱼头的Web海洋 公号 / 陈大鱼头 (本文来自作者投稿) 介 ...

  8. 一款超好用的第三方评论插件--Gittalk

    使用GITALK的背景: 1. 最近在做一个基于Java的个人博客系统,已经基本完工了,突然发现怎么没有评论的操作,如果再从头开始从数据库开始写的话,花费的代价有点大,于是乎我就在网上寻找一款适合我的 ...

  9. 一些特殊的矩阵快速幂 hdu5950 hdu3369 hdu 3483

    思想启发来自, 罗博士的根据递推公式构造系数矩阵用于快速幂 对于矩阵乘法和矩阵快速幂就不多重复了,网上很多博客都有讲解.主要来学习一下系数矩阵的构造 一开始,最一般的矩阵快速幂,要斐波那契数列Fn=F ...

  10. 在做nios ii uart232 实验时出现undefined reference to `fclose'等错误。

    程序如下 #include<stdio.h> #include<string.h> #include "system.h"   int main () { ...