简介

在系统开发中,日志是很重要的一个环节,日志写得好对于我们开发调试,线上问题追踪等都有很大的帮助。但记日志并不是简单的输出信息,需要考虑很多问题,比如日志输出的速度,日志输出对于系统内存,CPU的影响等,为此,出现了很多日志框架,以帮助开发者解决这些问题。

java中的常用日志框架

比较常用的有Log4j,SLF4j,Commons-logging,logback。当然,JDK本身也提供了java.util.logging包来提供对日志的支持。

Commons-loggin:是apache最早提供的日志的门面接口。它的主要作用是提供一个日志门面,使用者可以使用不同的日志实现。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。common-logging内部有一个Simple logger的简单实现,但是功能很弱。

SLF4j:是Simple Logging Facade for Java的简称,即java的简单日志门面。类似于Apache Common-Logging,是对不同日志框架提供的一个门面封装,可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,他在编译时静态绑定真正的Log库。使用SLF4J时,如果你需要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合(各种桥接包)。

Log4j:经典的一种日志解决方案。内部把日志系统抽象封装成Logger 、appender 、pattern等实现。我们可以通过配置文件轻松的实现日志系统的管理和多样化配置。pache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIXSyslog守护进程等;用户也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,用户能够更加细致地控制日志的生成过程。这些可以通过一个 配置文件来灵活地进行配置,而不需要修改程序代码。

logback:也是一种日志实现。Logback是由log4j创始人设计的又一个开源日记组件。logback当前分成三个模块:logback-core,logback-classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个改良版本。此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日记系统如log4j或JDK14Logging。logback-access访问模块与Servlet容器集成提供通过Http来访问日记的功能。

各个框架之间的关系

上面说了这么多日志框架,它们之间是怎样的关系呢? 
1. commons-logging和slf4j是java中的日志门面,即它们提供了一套通用的接口,具体的实现可以由开发者自由选择。log4j和logback则是具体的日志实现方案。 
2. 它们可以理解为接口与实现类的关系 
3. 四个框架都可以在程序中使用,但是为了考虑扩展性,一般我们在程序开发的时候,会选择使用commons-logging或者slf4j这些日志门面,而不是直接使用log4j或者logback这些实现。即我们写代码的时候导入的类一般都是来自门面框架中的类,然后将某个日志的实现框架加入到项目中,提供真正的日志输出功能。 
4. 比较常用的搭配是commons-logging+log4j,slf4j+logback

下面的图描述的挺好: 

日志框架的门面模式

门面模式,是面向对象设计模中的结构模式,又称为外观模式。外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 
简单理解就是通过通过门面模式对外提供一个统一的调用接口,屏蔽子系统之间复杂的调用关系,对客户端来讲,使用起来更容易。

commons-logging和slf4j就是这样,它们提供了日志的更高层次的抽象,具体的实现使用者不需要关心,而且可以自由选择。

使用举例

在开发中,我们一般不会直接使用某个具体的日志框架(比如log4j和logback),而是使用commons-logging和slf4j,这样做的好处是,我们可以自由选择日志实现。 
特别是对于一些开源框架来说更是如此,在提供给其他人使用的时候,使用我们框架的人使用的日志框架是复杂多变的,不确定的,所以如果我们开源框架里选择了一个具体的日志实现,而碰巧这个日志实现的可扩展性和兼容性又不好,那么使用我们开源框架的人为了满足我们框架的日志,就只能跟我们框架用一样的日志实现,否则打印日志可能就会有问题。这样一来,使用我们框架的开发者的自由度就降低了。

基于commons-logging的日志使用

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class XXXService {
private static final Log log = LogFactory.getLog(XXXService.class);
public void doSomething(){
log.info("begin dosomething....");
}
}

基于slf4j的日志使用

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class XXXService {
private static final Logger logger = LoggerFactory.getLogger(XXXService.class);
public void doSomething() {
logger.info("begin dosomething...");
}
}

上面的两种方式,引入的包都是门面日志框架的包,而不是具体某个实现的包。

Commons-logging和SLF4j实现机制

使用门面模式,如果门面模式本身不提供日志实现,那么我们还是不能正确打印日志的。所以还需要通过门面模式能够找到其实现类。就跟接口与实现类一样。 
那么,日志的门面框架是如何与实现框架建立关系的呢?

Commons-logging

common-logging通过动态查找的机制,在程序运行时自动找出真正使用的日志库。由于它使用了ClassLoader寻找和载入底层的日志库,导致了象OSGI这样的框架无法正常工作,因为OSGI的不同的插件使用自己的ClassLoader。OSGI的这种机制保证了插件互相独立,然而却使Apache Commons-Logging无法工作。

SLF4j

slf4j在编译时静态绑定真正的Log库,因此可以再OSGI中使用。它是通过查找类路径下org.slf4j.impl.StaticLoggerBinder,然后绑定工作都在这类里面进行,如果发现类路径下有多个StaticLoggerBinder,会给出警告。

slf4j提供了针对各种日志框架的迁移方案,并未这些方案提供了各种桥接框架。 
关于SLF4j,它的官方文档讲解的很好,可以参考这里

为什么要用SLF4J+Logback 替换commons-logging+log4j?

  1. SLF4J是编译时绑定到具体的日志框架,性能优于采用运行时搜寻的方式的commons-logging
  2. SLF4J提供了更好的日志记录方式,带来下这几方面的好处:1、更好的可读性;2、不需要使用logger.isDebugEnabled()来解决日志因为字符拼接产生的性能问题。比如:logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol); 官方文档:这里
  3. logback支持了更方便的自定义日志,便于后期的日志分析,可以将日志格式化保存到各种存储引擎中,请点击这里 可以将日志写入到HBase等。

补充一点

分析下面两行代码的区别:

logger.info("my name is {}", "medusar");
logger.info("my name is " + "medusar");

在效率上,第一行比第二行更高,因为如果当前日志级别是ERROR,第一行不会进行字符串拼接,而第二行,无论日志级别是什么,都会先进行字符串拼接。 
所以为了解决这个问题,commons-logging等框架提供了下面的方式:

if (log.isDebugEnabled()){
log.debug("dddd"+"eee");
}

而slf4j却不需要,因为它的日志级别不满足的时候会进行字符串拼接。

参考资料

  1. http://www.cnblogs.com/zhuawang/p/3999235.html
  2. http://blog.csdn.net/yycdaizi/article/details/8276265
  3. https://segmentfault.com/a/1190000000370671
  4. http://singleant.iteye.com/blog/934593

转自:http://blog.onlycatch.com/post/cfbc30f8d1ba



												

Java日志框架(Commons-logging,SLF4j,Log4j,Logback)的更多相关文章

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

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

  2. Java日志框架 (commons-logging,log4j,slf4j,logback)

    转自:http://blog.csdn.net/kobejayandy/article/details/17335407 如果对于commons-loging.log4j.slf4j.LogBack等 ...

  3. Java日志框架:SLF4J,Common-Logging,Log4J,Logback说明

    Log4j  Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务 器.NT的事件记录器.UNIX Syslog守护进程等 ...

  4. 日志框架之2 slf4j+logback实现日志架构 · 远观钱途

    如何从缤纷复杂的日志系统世界筛选出适合自己的日志框架以及slf4j+logback的组合美妙之处?此文可能有帮助 logback介绍 Logback是由log4j创始人设计的另一个开源日志组件,官方网 ...

  5. SpringBoot日志logback-spring.xml分环境log4j logback slf4j区别 springboot日志设置

    转载. https://blog.csdn.net/qianyiyiding/article/details/76565810 springboot按照profile进行打印日志log4j logba ...

  6. java日志框架系列(1):slf4j框架简介及依赖

    1.slf4j日志框架 1.简介 slf4j只是是日志规范,即只定义了接口,并没有实现这些接口. SLF4J的全称是Simple Logging Facade for Java,即简单日志门面.SLF ...

  7. java日志框架系列(4):logback框架xml配置文件语法

    1.xml配置文件语法 由于logback配置文件语法特别灵活,因此无法用DTD或schema进行定义. 1.配置文件基本结构 配置文件基本结构:以<configuration>标签开头, ...

  8. Java 日志框架终极教程

    概述 对于现代的 Java 应用程序来说,只要被部署到真实的生产环境,其日志的重要性就是不言而喻的,很难想象没有任何日志记录功能的应用程序被运行于生产环境中.日志 API 所能提供的功能是多种多样的, ...

  9. slf4j log4j logback关系详解和相关用法

    slf4j log4j logback关系详解和相关用法 写java也有一段时间了,一直都有用slf4j log4j输出日志的习惯.但是始终都是抱着"拿来主义"的态度,复制粘贴下配 ...

随机推荐

  1. Vijos1906 联合权值 NOIP2014Day1T2 树形动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - Vijos1906 题意概括 有一棵树,每一个节点都有一个权值w[i].下面说的x,y都是该树中的节点. 对于 ...

  2. Mistwald POJ

    一开始看不出来是快速幂矩阵的题目 先要把整个地图离散化为1,2,3,4,.... 连成一个有向图 邻接矩阵的平方意为:假如a->b  且b->c     那么一次平方后   a->c ...

  3. 【目录】LeetCode Java实现

    这里记录一下自己刷的LeetCode题目. 有些博客用英文阐述自己的思路和收获,相当于练习一下英文的表达能力. 比较好的题目有加粗. 1. Two Sum 3. Longest Substring W ...

  4. 模拟页面获取的php数据(二)

    <?php return [ "aData" => [//通勤方式 "trafficType" => [ 0 => [ "ty ...

  5. 潭州课堂25班:Ph201805201 python 模块 datetime,logging 第七课 (课堂笔记)

    datetime 模块 # -*- coding: utf-8 -*-# 斌彬电脑# @Time : 2018/7/9 0009 20:42import datetime d = datetime.d ...

  6. 2、函数y=f(x)

    /* Note:Your choice is C IDE */ #include "stdio.h" /* 3.函数y=f(x)可表示为: */ void main() { int ...

  7. vi 命令 行首、行尾

    vim 跳到行首 : 数字 0 vim跳到行位 : $  [Shift + 4]

  8. unity3d脚本语言中的引用类型

    在之前的文文里有说到,值类型和引用类型,那么这会就单独说下引用类型: Unity3D中的C#语言提供了专门的类型来为开发者提供使用C#开发游戏的便利条件: 在该引擎中,使用UnityEngine命名空 ...

  9. 2016年7款最佳 Java 框架

    毫无疑问,Java 是目前最为流行的编程语言之一,这里我们挖掘出了一些比较受欢迎的框架的有效信息,它们可以减轻全球软件开发人员的日常工作. RebelLabs的一项调查显示,通过在线Java用户论坛( ...

  10. 13.1 dubbo服务降级源码解析

    从 9.1 客户端发起请求源码 的客户端请求总体流程图中,截取部分如下: //代理发出请求 proxy0.sayHello(String paramString) -->InvokerInvoc ...