为什么使用 SLF4J 而不是 Log4J 来做 Java 日志 已翻译 100%

lwei 投递于 2013/10/21 15:44 (共 5 段, 翻译完成于 10-22)
阅读 112253
收藏 56
8
加载中
Every Java programmers knows that logging is critical for any Java application, especially server side application, and many of them are already familiar with various logging libraries e.g. java.util.logging, Apache log4j, logback, but if you don't know about SLF4J, Simple logging facade for Java,  then it's time to learn and use SLF4J in your project. In this Java article, we will learn why using SLF4J is better than using log4j or java.util.logging. It’s been long time, since I wrote 10 logging tips for Java programmer,I don’t remember anything I have writing about logging. Anyway, let’s get back to topic, on contrary to all those logging libraries, there is a major difference between them and SLF4J. SLF4J or Simple logging Facade for Java is not really a logging implementation, instead it's an abstraction layer, which allows you to use any logging library in back-end. If you are writing API or utility library, which can be used internally or externally, then you really don't want that any client, which uses your library, should also stick with your choice of logging library. Suppose if a project is already using log4j, and you included a library say Apache Active MQ, which has dependency on logback, another logging library, then you need to include them as well, but if Apache Active MQ uses SL4J, you can continue with your logging library, without pain of adding and maintaining new logging framework. In short SLF4J make your code independent of any particular logging API, which is good think for public API developers. Though idea of abstracting logging library is not new and Apache commons logging is already using it, but now SLF4J is quickly becoming an standard for logging in Java world. Let's see couple of more reason to use SLF4J over log4j, logback or java.util.logging.
已有 2 人翻译此段
我来翻译

Prefer SLF4J over Log4J, logback and java.util.Logging

As I said earlier, main motivation of using SLF4J in your code to write log statements is, to make your program, independent of any particular logging library, which might require different configuration than you already have, and introduce more maintenance headache. But apart from that, there is one more feature of SLF4J API, which convinced me to use SL4J over my long time favorite Log4j, that is know as place holder and represented as {} in code. Placeholder is pretty much same as %s in format() method of String, because it get substituted  by actual string supplied at runtime. This not only reduce lot of String concatenation in your code, but also cost of creating String object. This is true even if you might not need that, depending upon your log level in production environment e.g. String concatenation on DEBUG and INFO levels. Since Strings are immutable and they are created in String pool, they consume heap memory and most of the time they are not needed e.g. an String used in DEBUG statement is not needed, when your application is running on ERROR level in production. By using SLF4J, you can defer String creation at runtime, which means only required Strings will be created. If you have been using log4j then you already familiar with a workaround of putting debug statement inside if() condition, but SLF4J placeholders are much better than that.

已有 1 人翻译此段
我来翻译

This is how you would do in Log4j, but surely this is not fun and reduce readability of code by adding unnecessary boiler-plate code.

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

On the other hand if you use SLF4J, you can get same result in much concise format as shown below :

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

In SLF4J, we don't need String concatenation and don't incur cost of temporary not need String. Instead, we write log message in a template format with placeholder and supply actual value as parameters. You might be thinking about what if I have multiple parameters, well you can either use variable arguments version of log methods or pass them as Object array. This is really convenient and efficient way of logging. Remember, before generating final String for logging message, this method check if a particular log level is enabled or not, which not only reduce memory consumption but also CPU time involved for executing those String concatenation instruction in advance. Here is the code of SLF4J logger method from it's Log4j Adapter class Log4jLoggerAdapter from slf4j-log4j12-1.6.1.jar.

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());
    }
}

It's also worth knowing that logging has severe impact on performance of application, and it's always advised to only mandatory logging in production environment.

已有 1 人翻译此段
我来翻译

How to use SLF4J with Log4J for logging

Apart from above benefits, I think there is one caveat though, in order to use SLF4J you not only need to include SLF4J API Jar e.g. slf4j-api-1.6.1.jar, but also companion JAR, depending upon which logging library, you are using in backend. Suppose If you want to use SLF4J, Simple Logging Facade for Java,  along with Lo4J, you need to include following jars in your classpath, depending upon which version of SLF4J and log4J you are using e.g.

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

If you are using Maven to mange dependency in your project, you can just include SLF4J JAR, and maven will include it's dependent companion JAR. In order to use Log4J along with SLF4J, you can include following dependency in your project's 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> 

By the way, if you are interested in using variable argument version of logger methods, than include SLF4J 1.7 version.

已有 1 人翻译此段
我来翻译

Summary

To summarize this post, I would suggest following reasons are good enough to choose SLF4J over Log4j, commons logging, logback or java.util.logging directly.

1) Using SLF4J in your open source library or internal library, will make it independent of any particular logging implementation, which means no need to manage multiple logging configuration for multiple libraries, your client will going to appreciate this.

2) SLF4J provides place holder based logging, which improves readability of code by removing checks lie isDebugEnabled(), isInfoEnabled() etc.

3) By using SLF4J logging method, you defer cost of constructing logging messages (String), until you need it, which is both memory and CPU efficient.

4) As a side note, less number of temporary strings means less work for Garbage Collector, which means better throughput and performance for your application.

These advantages are just tip of iceberg, you will learn about more benefits, when you start using SL4J and reading about it.  I strongly suggest, any new code development in Java, should use SLF4J for logging over any other logging API including log4J.

已有 2 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(12)

j
jasonbournehu
好文章,就是前面两大段文字废话太多
a
ausky
学习了 👍
非沧海一粟不随波逐流
非沧海一粟不随波逐流
66666 怒赞
qwfys
qwfys
不错,
小白爱吃肉
小白爱吃肉
是多少
消热
消热
SLF4J 定义的是一套规范,很多都没有实现。。。要想日志落地,你还是得集成下日志系统,你这标题有点过了
小雪纷飞
小雪纷飞
赞,这些东西不看源码,道听途说很难真正理解。
slf4j.jar只是定义了日志接口,slf4j-log4j.jar将slf4j接口实现转向log4j的日志实现
20U志伟
20U志伟
强!
netkiller-
netkiller-
SLF4J 能将日志送入 MQ ??
另一端通过 MQ 接收,并将 日志落地?
chng
chng
IoC原则
返回顶部
顶部