文档章节

为什么要使用slf4j而不是log4j

zhenchao
 zhenchao
发布于 2016/08/07 02:12
字数 1999
阅读 116
收藏 7

  每一个Java程序员都知道日志对于任何一个Java应用程序,尤其是服务端程序是至关重要的,而很多程序员也已经熟悉各种不同的日志库如java.util.logging、Apache log4j、logback。但如果你还不知道slf4j的话,那么是时候去在你项目中学习使用slf4j了。

  在这篇文章中,我们将学习为什么使用slf4j比log4j或者java.util.logging要优秀。自从上次我写Java程序员的10个日志技巧已经有一段时间了,我已经不记得我写的关于日志的一切了。

  不管怎样,让我们回到这个话题,slf4j不同于其他日志类库,与其它有很大的不同。 slf4j不是一个真正的日志实现,而是一个抽象层(abstraction layer),它允许你在后台使用任意一个日志类库。如果是在编写供内外部都可以使用的API或者通用类库,那么你真不会希望使用你类库的客户端必须使用你选择的日志类库。

  如果一个项目已经使用了log4j,而你加载了一个类库,比方说 Apache Active MQ——它依赖于于另外一个日志类库logback,那么你就需要把它也加载进去。但如果Apache Active MQ使用了slf4j,你可以继续使用你的日志类库而无语忍受加载和维护一个新的日志框架的痛苦。

  总的来说,slf4j使你的代码独立于任意一个特定的日志API,这是一个对于开发API的开发者很好的思想。虽然抽象日志类库的思想已经不是新鲜的事物而且Apache commons logging也已经在使用这种思想了,但现在slf4j正迅速成为Java世界的日志标准。让我们再看看几个使用slf4j而不是log4j、logback或者java.util.logging的理由。

- slf4j对比log4j,logback和java.util.Logging的优势

  正如我之前说的,在你的代码中使用slf4j写日志语句的主要出发点是使得你的程序独立于任意特定的日志类库,依赖于特定类可能需要不同与你已有的配置,并且导致更多维护的麻烦。但除此之外,还要一个slf4j API的特性使得我坚持使用slf4j而抛弃我长期间钟爱的Lof4j的理由,是被称为占位符(place holder),在代码中表示为“{}”的特性。占位符是一个非常类似于在String的format()方法中的%s,因为它会在运行时被某个提供的实际字符串所替换。这不仅降低了你代码中字符串连接次数,而且还节省了新建的String对象。即使你可能没需要那些对象,但这个依旧成立,取决于你的生产环境的日志级别,例如在DEBUG或者INFO级别的字符串连接。因为String对象是不可修改的并且它们建立在一个String池中,它们消耗堆内存( heap memory)而且大多数时间他们是不被需要的,例如当你的应用程序在生产环境以ERROR级别运行时候,一个String使用在DEBUG语句就是不被需要的。通过使用slf4j,你可以在运行时延迟字符串的建立,这意味着只有需要的String对象才被建立。而如果你已经使用log4j,那么你已经对于在if条件中使用debug语句这种变通方案十分熟悉了,但slf4j的占位符就比这个好用得多。

  这是你在log4j中使用的方案,但肯定这一点都不有趣并且降低了代码可读性因为增加了不必要的繁琐重复代码(boiler-plate code):

if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
}

另一方面,如果你使用slf4j的话,你可以得到在极简洁的格式的结果,就像以下展示的一样:

logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);

  在slf4j,我们不需要字符串连接而且不会导致暂时不需要的字符串消耗。取而代之的,我们在一个以占位符和以参数传递实际值的模板格式下写日志信息。你可能会在想万一我有很个参数怎么办?嗯,那么你可以选择使用变量参数版本的日志方法或者用以Object数组传递。这是一个相当的方便和高效方法的打日志方法。记住,在生产最终日志信息的字符串之前,这个方法会检查一个特定的日志级别是不是打开了,这不仅降低了内存消耗而且预先降低了CPU去处理字符串连接命令的时间。这里是使用slf4j日志方法的代码,来自于slf4j-log4j12-1.6.1.jar中的log4j的适配器类log4jLoggerAdapter。

public void debug(String format, Object arg1, Object arg2) {
    if (logger.isDebugEnabled()) {
        FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
        logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
    }
}

  同时,我们也很值得知道打日志是对应用程序的性能有着很大影响的,在生产环节上只进行必要的日志记录是我们所建议的。

- 怎么用slf4j做log4j的日志记录

  除了以上好处,我想还有一个告诫,就是为了使用slf4j,你不仅需要包含slf4j的API jar包,例如 slf4j-api-1.6.1.jar,还需要相关Jar包,这取决于你在后台使用的日志类库。如果你想要使用和log4j 一起使用slf4j,你需要包含以下的Jar包在你的CLASSPATH中,取决于哪个slf4j和你在使用的log4j的版本。例如:

slf4j-api-1.6.1.jar – JAR for slf4j API
log4j-1.2.16.jar – JAR for log4j API
slf4j-log4j12-1.6.1.jar – log4j Adapter for slf4j

  如果你在使用Maven去管理你的项目依赖,你只需要包含slf4j JAR包,maven会包含它的依赖的相关包。为了和slf4j一起中使用log4j,你可以包含以下的依赖在你项目中的pom.xml。

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.1</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.1</version>
</dependency>

  还有,如果你对于使用变量参数版本(variable argument version )的日志方法感兴趣的话,那么就导入slf4j 1.7的版本吧。

- 总结

  总结这次说的,我建议使用slf4j的而不是直接使用log4j, commons logging, logback 或者 java.util.logging已经足够充分了。

  1. 在你的开源或内部类库中使用slf4j会使得它独立于任何一个特定的日志实现,这意味着不需要管理多个日志配置或者多个日志类库,你的客户端会很感激这点。
  2. slf4j提供了基于占位符的日志方法,这通过去除检查isDebugEnabled(), isInfoEnabled()等等,提高了代码可读性。
  3. 通过使用slf4j的日志方法,你可以延迟构建日志信息(Srting)的开销,直到你真正需要,这对于内存和CPU都是高效的。
  4. 作为附注,更少的暂时的字符串意味着垃圾回收器(Garbage Collector)需要做更好的工作,这意味着你的应用程序有为更好的吞吐量和性能。
  5. 这些好处只是冰山一角,你将在开始使用SL4J和阅读其中代码的时候知道更多的好处。我强烈建议,任何一个新的Java程序员,都应该使用slf4j做日志而不是使用包括log4j在内的其他日志API。

本文转载自:http://www.importnew.com/7450.html

共有 人打赏支持
zhenchao
粉丝 105
博文 28
码字总数 98844
作品 0
海淀
高级程序员
为什么要使用 SLF4J 而不是 Log4J

本文由 ImportNew - Jaskey 翻译自 javarevisited。如需转载本文,请先参见文章末尾处的转载要求。 每一个Java程序员都知道日志对于任何一个Java应用程序,尤其是服务端程序是至关重要的,而...

编走编想
2013/12/07
0
0
commons-logging,log4j,logback,slf4j之间的关系详解。

commons-logging 是apache最早提供的日志的门面接口。它的主要作用是提供一个日志门面,使用者可以使用不同的日志实现。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带...

java技术栈
2017/08/13
0
0
slf4j、jcl、jul、log4j1、log4j2、logback大总结

1 系列目录 - jdk-logging、log4j、logback日志介绍及原理- commons-logging与jdk-logging、log4j1、log4j2、logback的集成原理- slf4j与jdk-logging、log4j1、log4j2、logback的集成原理- s...

乒乓狂魔
2015/05/04
0
33
解密Log4j、SLF4J、Common-logging的区别

前面有一篇日志中简单的介绍了 log4j,同时也介绍了它与commons-logging的关系,但是突然冒出来一个slf4j,并且slf4j有取代commons-logging的趋势,所以,我们可以推知slf4j与commons-loggi...

yntmdr
07/26
0
0
比较 SLF4J 与 log4j

SLF4J :JAVA简易日志门面(Simple Logging Facade for Java,缩写SLF4J) 他是一套包装Logging 框架的接口程式,以外观模式实现。可在软件部署的时候决定要使用的 Logging 框架,目前主要支援...

Candy_Desire
2014/03/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

原型模式

1、原型模式-定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 克隆(浅度克隆->拷贝值类型或者引用,深度克隆->创建新的对象,开辟新的内存) 例如客户端知道抽象Pro...

阿元
今天
32
0
awk命令扩展使用操作

awk 中使用外部shell变量 示例1 [root@centos01 t1022]# A=888[root@centos01 t1022]# echo "" | awk -v GET_A=$A '{print GET_A}'888[root@centos01 t1022]# echo "aaaaaaaaaaaaa" | aw......

野雪球
今天
29
0
深入解析MySQL视图VIEW

Q:什么是视图?视图是干什么用的? A:视图(view)是一种虚拟存在的表,是一个逻辑表,本身并不包含数据。作为一个select语句保存在数据字典中的。   通过视图,可以展现基表的部分数据;...

IT--小哥
今天
38
0
虚拟机学习之二:垃圾收集器和内存分配策略

1.对象是否可回收 1.1引用计数算法 引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时候计数器值为0的对象就是不可能...

贾峰uk
今天
25
0
smart-doc功能使用介绍

smart-doc从8月份底开始开源发布到目前为止已经迭代了几个版本。在这里非常感谢那些敢于用smart-doc去做尝试并积极提出建议的社区用户。因此决定在本博客中重要说明下smart-doc的功能,包括使...

上官胡闹
昨天
38
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部