JCL、SLF4J、Log4J、Log4J2、LogBack和JUL之间的关系,你搞清楚了吗?
写在前面
日志组件是我们平时开发过程中必然会用到的组件。在系统中正确的打印日志至少有下面的这些好处:
- 调试:在程序的开发过程中,必然需要我们不断的调试以达到程序能正确执行的状态 。记录日志可以让开发人员清楚的了解程序的运行状态定位问题;
- 信息收集:在
DT
时代,谁掌握了数据谁就掌握了主动权。现在主流的日志系统可以非常方便的记录用户行为数据,格式化成便于进行大数据分析的格式; - 记录运行状态:应用程序投产之后,难免会出现生产事故,有了系统日志工程师可以根据日志迅速定位问题。
当然,硬币都具有两面性。引入日志组件也并不是没有缺点。
- 代码冗余:光从实现业务逻辑的角度来讲,在应用程序中插入打印日志的代码打印一大堆日志是完全没必要的,这在一定程度上降低了代码的可读性;
- 降低系统性能:这点很容易理解,因为需要进行日志打印处理,所以系统的运行速度肯定会有所降低。
综合比较日志组件优缺点,我们发现引入日志组件还是非常有必要的。
在我们平时的开发过程中,常用的日志组件有Log4J、Log4J2和LogBack等。代码中,我们一般都是像下面这样使用它们的。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableAdminServer
public class AppQuickStart {
private static Logger logger = LoggerFactory.getLogger(AppQuickStart.class);
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
logger.info("app begin to start...");
SpringApplication.run(AppQuickStart.class, args);
logger.info("app start success...");
}
}
或者是像下面这样
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableAdminServer
public class AppQuickStart {
private static final Log logger = LogFactory.getLog(AppQuickStart.class);
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
logger.info("app begin to start...");
SpringApplication.run(AppQuickStart.class, args);
logger.info("app start success...");
}
}
上面的两段代码很相似,是我们引入日志的模板代码,唯一有区别的地方是第一段代码引入了SLF4J
的Jar包,第二段代码引入了common-logging
的Jar包(后面简称JCL)。
刚开始接触日志组件的时候,我对这样的使用方式感到很疑惑:我们不是要用使用Log4J
或者是LogBack
打日志么,怎么完全没见到Log4J
和LogBack
的影子,反而有冒出来两个新框架SLF4J
和common-logging
。
那么这两个框架到底有什么作用?和Log4J
、Log4J2
还有LogBack
又是什么关系?如果你也有这样的疑问,说明你还是善于思考的。今天的文章就来介绍下JCL
、SLF4J
、Log4J
、Log4J2
、LogBacky
以及JUL
(JUL的存在感很低,哈哈~)之间的关系。
门面模式
学过设计模式的同学都会知道在23种设计模式中有一种模式叫门面模式。
以上是门面模式的结构图。
在这个结构图中,出现了两个角色:
- 门面(Facade)角色 :客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
- 子系统(SubSystem)角色 :可以同时有一个或者多个子系统。每个子系统都不是一个单独的类,而是一个类的集合(如上面的子系统就是由ModuleA、ModuleB、ModuleC三个类组合而成)。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。
使用门面模式具有以下优点
- 松散耦合: 门面模式松散了客户端与子系统的耦合关系,让子系统内部的模块能更容易扩展和维护。
- 简单易用: 门面模式让子系统更加易用,客户端不再需要了解子系统内部的实现,也不需要跟众多子系统内部的模块进行交互,只需要跟门面类交互就可以了。
- 更好的划分访问层次: 通过合理使用Facade,可以帮助我们更好地划分访问的层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到门面中,这样既方便客户端使用,也很好地隐藏了内部的细节。
JCL
和SLF4J
为什么要介绍上面的门面模式呢?因为现今主流的日志组件都是使用门面模式实现的。而JCL
和SLF4J
就是门面模式中的Facade
角色。
JCL
官网对JCL
的介绍:
The Logging package is an ultra-thin bridge between different logging implementations. A library that uses the commons-logging API can be used with any logging implementation at runtime. Commons-logging comes with support for a number of popular logging implementations, and writing adapters for others is a reasonably simple task. ——JCL官网
上面英文的大致意思是:JCL
是不同日志实现之间的一座“桥梁”,JCL
支持许多主流的日志实现。而且自己编写JCL
的适配代码也很简单。
SLF4J
的介绍:
The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks (e.g. java.util.logging, logback, log4j) allowing the end user to plug in the desired logging framework at deployment time. —— SLF4J官网
上面英文的大致意思是:SLF4J
充当不同日志框架门面的角色,让用户可以自由切换底层的日志实现。
通过上面的介绍,我们可以知道JCL
和SLF4J
都是日志门面(Facade),而Log4J
、Log4J2
和LogBack
都是子系统角色(SunSystem),也就是具体的日志实现框架。他们的关系如下。
使用日志门面引入日志组件的最大优势是:将系统和具体的日志实现框架解耦合。
假如说我们不使用日志门面,直接使用特定的日志框架(比如说Log4J
)的API进行编程,那么我们势必会在每个类中都耦合Log4J
的API,如果你的系统一直使用Log4j作为日志实现,那OK。一旦有一天你老板心血来潮觉得Log4J
不能满足系统的需求了(这边只是举个栗子,Log4J
还是很强大_),指派你将Log4J更换成其他的日志实现。我想此刻的你一定会有点懵逼。因为你需要修改每个类中耦合的Log4J
API。
如果使用JCL或者SLF4J等日志门面很好的帮我们解决了这种问题,我们不需要修改代码,只需要更换日志实现框架即可。
Log4J、Log4J2和LogBack的有趣历史
使用过Log4J
和LogBack
的同学肯定能发现,这两个框架的设计理念极为相似,使用方法也如出一辙。
其实这个两个框架的作者都是一个人,Ceki Gülcü,俄罗斯程序员。
Log4J
最初是基于Java开发的日志框架,发展一段时间后,作者Ceki Gülcü将Log4j
捐献给了Apache软件基金会,使之成为了Apache日志服务的一个子项目。 又由于Log4J
出色的表现,后续又被孵化出了支持C, C++, C#, Perl, Python, Ruby等语言的子框架。
然而,伟大的程序员好像都比较有个性。Ceki Gülcü由于不满Apache对Log4J
的管理,决定不再参加Log4J
的开发维护。“出走”后的Ceki Gülcü另起炉灶,开发出了LogBack
这个框架(SLF4J
是和LogBack
一起开发出来的)。
LogBack
改进了很多Log4J
的缺点,在性能上有了很大的提升,同时使用方式几乎和Log4J
一样,许多用户开始慢慢开始使用LogBack
。
由于受到LogBack
的冲击,Log4J
开始式微。终于,2015年9月,Apache软件基金业宣布,Log4j
不在维护,建议所有相关项目升级到Log4j2
。
Log4J2
是Apache开发的一个新的日志框架,改进了很多Log4J
的缺点,同时也借鉴了LogBack
,号称在性能上也是完胜LogBack
。有兴趣的朋友可以测试下两者的性能。
这边顺带提下JUL
这个日志组件。这个日志组件是JDK自带的日志框架。由于在使用便利性和性能上都欠佳,所以存在感一直不高。
简单总结
JCL
和SLF4J
功能一样,都是日志门面,使用它们引入日志组件的目的是将系统和具体的日志实现之间解耦;Log4J
、Log4J2
、LogBack
和JUL
都是具体的日志实现。使用时要和门面日志搭配使用。
参考
JCL、SLF4J、Log4J、Log4J2、LogBack和JUL之间的关系,你搞清楚了吗?的更多相关文章
- 常见java日志系统的搭配详解:关于slf4j log4j log4j2 logback jul jcl commons-logging jdk-logging
先看一张图: 是不是有点晕, 晕就对了.这个仅仅是 slf4j 的情况,实际上, 我们不仅要接触到 slf4j ,有时候还会接触其他的日志系统.且看下文分解. 1 直接使用各个日志系统 1.1 直接使 ...
- Log4j,Log4j2,logback,slf4j日志学习
日志学习笔记 Log4j Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.数据库等:我们也可以控制每一条日志的输出格式:通过定义每一条 ...
- Log4j,Log4j2,logback,slf4j日志学习(转)
日志学习笔记Log4jLog4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.数据库等:我们也可以控制每一条日志的输出格式:通过定义每一条日志 ...
- 关于slf4j log4j log4j2的jar包配合使用的那些事
由于java日志框架众多(common-logging,log4j,slf4j,logback等),引入jar包的时候,就要为其添加对应的日志实现.. 不同的jar包,可能用了不同的日志框架,那引用了 ...
- Java日志之Slf4j,Log4J,logback原理总结
几乎任何应用,一定是需要日志的. 那么,面对种类繁多的日志框架和配置,我们该何去何从? 1.前奏:我是在研究mybatis源码的过程中才意识到需要搞明白日志原理这回事,因为mybatis(和一些其他开 ...
- 日志套餐篇 - log4j2 logback全量套餐
日志套餐篇 - log4j2 logback全量套餐 前情提要: Log4j Log4j2 logback是当下主流的日志框架 slf4j则是新一代的日志框架接口,logback直接实现了slf4j接 ...
- slf4j log4j logback log4j2关系详解和相关用法
来源:slf4j log4j logback关系详解和相关用法https://www.cnblogs.com/Sinte-Beuve/p/5758971.html The Simple Logging ...
- log4j 、logback 以及slf4j三者之间的关系
在项目的开发中由于对于log4j.logback以及slf4j之间的关系和相关的知识不能清晰掌握,在业余时间进行记录. 1.三者之间的关系 1) 简答的讲就是slf4j是一系列的日志接口,而log4j ...
- slf4j,log4j,logback 初步使用
log4j,slf4j,logback简单介绍见 LogBack简易教程 Logback浅析 简单的将,slf4j是一个日志的框架,有各种日志的接口,但是并不包含实际的写日志的方法. log4j,lo ...
随机推荐
- Java对象头与锁
对象由多部分构成的,对象头,属性字段.补齐区域等.所谓补齐区域是指如果对象总大小不是4字节的整数倍,会填充上一段内存地址使之成为整数倍. 后面两个很好理解,今天我主要想总结一下对象头: 对象头这部分在 ...
- [转]C#中的abstract 类和方法
转:https://www.cnblogs.com/zzy2740/archive/2005/09/20/240808.html C#中的abstract类不能被实例化,他只提供其他类的继承的接口 u ...
- Date类与日期格式
Date类概述: 表示特定的瞬间,精确到毫秒. Date()分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒).Date(long date)分配 Date 对象并初始化此对象,以表 ...
- Spring--2.Spring之IOC--IOC容器的23个实验(1)
实验1.IOC容器创建对象,并为属性赋值 Hello World:(通过各种方式给容器中注册对象(注册会员)) 以前是自己new对象,现在所有对象交给容器创建:给容器中注册组件 以后框架编写流程: ...
- 递推预处理 + Manacher
链接:https://www.nowcoder.com/acm/contest/131/D来源:牛客网 字符串 S 只包含小写英文字母.有四种操作,每次操作你可以选择其中一种: 删除字符串的第一个字母 ...
- hadoop 基础
common 一组分布式文件系统和通用I/O的组件与接口(序列化.java RPC和持久化数据结构) Avro 一种支持高效.跨语言的RPC以及永久存储数据的序列化系统 MapReduce 分布式数据 ...
- python中常⽤的excel模块库
python中常用的excel模块库&安装方法 openpyxl openpyxl是⼀个Python库,用于读取/写⼊Excel 2010 xlsx / xlsm / xltx / xltm⽂ ...
- windows环境下使用python3.x自带的CGI服务器测试cgi脚本(转)
1.在桌面上新建一个文件夹作为服务器目录文件夹(文件夹名称自定义,文件夹位置自定义),在www文件下再建一个文件夹,文件夹名为“cgi-bin”,须是这个文件名,其他试过不行(原因暂时未知)
- Ndarry对象
创建一个 ndarray 只需调用 NumPy 的 array 函数即可: numpy.array(object, dtype = None, copy = True, order = None, s ...
- 60 个让程序员崩溃的瞬间,太TM真实了
前方高能!笑死人不偿命系列~ 表演即将开始,吃东西的请停下来,不然你会后悔的 1. 公司实习生找 Bug 2. 在调试时,将断点设置在错误的位置 3. 当我有一个很棒的调试想法时 4. 偶然间看到自己 ...