每一个Java程序员都知道日志对于任何一个Java应用程序,尤其是服务端程序是至关重要的,而很多程序员也已经熟悉各种不同的日志库如java.util.logging、Apache log4j、logback。但如果你还不知道SLF4J(Simple logging facade for Java)的话,那么是时候去在你项目中学习使用SLF4J了。
在这篇文章中,我们将学习为什么使用SLF4J比log4j或者java.util.logging要优秀。
不管怎样,让我们回到这个话题,SLF4J不同于其他日志类库,与其它有很大的不同。SLF4J(Simple logging Facade for Java)不是一个真正的日志实现,而是一个抽象层( 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 ,Simple Logging Facade for Java,,你需要包含以下的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>
还有,如果你对于使用变量参数版本(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)需要做更好的工作,这意味着你的应用程序有为更好的吞吐量和性能。
- 这些好处只是冰山一角,你将在开始使用SL4J和阅读其中代码的时候知道更多的好处。我强烈建议,任何一个新的Java程序员,都应该使用SLF4J做日志而不是使用包括Log4J在内的其他日志API。
相关推荐
在使用SLF4J之前,首先需要在项目的类路径中包含SLF4J的API jar包以及一个具体的日志实现库,例如Logback或Log4j。在Maven项目中,可以在pom.xml文件中添加以下依赖: ```xml <!-- SLF4J API --> <groupId>...
Springboot 项目使用 Slf4j 将日志保存到本地目录的实现代码 Slf4j 是一个 Java 日志记录门面,它提供了一个通用的日志记录API,允许开发者使用不同的日志记录框架,例如 Logback、Log4j 等。在 Springboot 项目中...
使用Slf4j集成Log4j2构建项目日志系统的完美解决方案 Slf4j是简单的日志外观(Facade)模式,它提供了统一的日志接口,使得用户可以选择不同的日志实现。Slf4j的出现使得日志系统的开发变得更加灵活和便捷。Log4j2...
slf4j-log4j12-1.7.x版本是SLF4J针对Log4j 1.2版本的绑定器,它使得应用可以使用SLF4J接口,但实际的日志输出通过Log4j进行。这个桥接器让项目能利用SLF4J的灵活性,同时使用Log4j的成熟实现。 在提供的文件名列表...
在某些场景下,比如测试环境中,你可能希望避免日志带来的额外开销,此时使用slf4j-nop.jar就非常合适。 标签"slf4j"直接指出了这个压缩包的主题,它是与SLF4J相关的资源。 压缩包内的文件名称列表中,"slf4j-api-...
SLF4J(Simple Logging Facade for Java)是一个用于Java编程语言的日志门面框架,它提供了一个简单的抽象层,用以使用各种日志框架,例如java.util.logging、logback和log4j。门面模式的好处在于,开发者可以在不同...
4. **编写日志代码**:在Java代码中,使用SLF4J的LoggerFactory获取Logger对象,然后调用相应级别的方法记录日志。 **日志框架的比较:** 1. **Log4j**:老牌的日志框架,功能强大,但配置相对复杂。SLF4J的一个...
具体来说,这个版本(1.7.12)的绑定包实现了SLF4J的API,并将其桥接到log4j的实现上,使得开发者可以通过SLF4J的API来使用log4j的功能。"slf4j-api-1.7.12.jar"则是SLF4J的核心API库,包含了所有SLF4J的日志记录...
Log4j2 结合 Slf4j 配置使用 Log4j2 是一个功能强大且广泛使用的日志记录工具,它提供了灵活的日志记录机制和高性能的日志记录能力。Slf4j 则是一个简单的日志记录门面,提供了统一的日志记录接口。今天,我们将...
2. `slf4j-jdk14-1.5.6.jar`:这是一个适配器模块,它使得Slf4j可以使用Java内置的日志系统(java.util.logging)作为其后台日志框架。如果你的应用环境中已经使用了Java内置的日志,那么这个适配器可以让Slf4j无缝...
然而,要注意的是,使用SLF4J时,你需要避免类路径中的“类装载器争抢”问题,即多个SLF4J绑定同时存在的情况,这会导致警告信息。为了避免这种情况,你需要确保项目中只包含一个SLF4J的绑定实现。 在实际应用中,...
描述中提到的"slf4j-api-1.7.26.jar"是SLF4J API的核心库,它包含所有开发者需要使用的接口和类,例如`org.slf4j.Logger`和`org.slf4j.LoggerFactory`。`Logger`接口提供了不同级别的日志记录方法,如`trace()`, `...
SLF4J(Simple Logging Facade for Java)是Java中一个重要的日志接口框架,它为各种日志实现提供了一个抽象层,使得开发者能够在运行时动态地选择具体使用的日志实现,例如Log4j、Java Util Logging (JUL)、Logback...
在使用SLF4J和Log4j12时,你需要注意的一点是,由于Log4j1.2相比Log4j2在某些方面可能较旧,例如性能和功能更新,因此在新项目中,你可能会考虑使用更新的SLF4J绑定器,如slf4j-log4j2,以便利用Log4j2的改进特性。...
4. **兼容性**: 使用NOP绑定不会影响SLF4J API的使用,因为API与实现之间是解耦的。 **使用SLF4J的好处** 1. **灵活性**: 开发者可以根据项目需求自由选择日志实现,只需更改配置即可。 2. **可移植性**: 应用程序...
在使用`slf4j-api-1.7.25`时,开发者应仔细阅读这个文件以了解如何正确集成到项目中,以及如何避免常见的问题,如“NoBindingException”,这通常是由于缺少适当的日志框架绑定导致的。 使用SLF4J的好处在于,它...
1. **slf4j.api-1.6.1.jar**:这是SLF4J的核心API库,包含了所有SLF4J的接口和注解,使得开发者可以在代码中使用SLF4J的API进行日志记录。例如,`org.slf4j.Logger`和`org.slf4j.LoggerFactory`是SLF4J中最常用的类...
4. **模块化**:SLF4J的设计使其易于在模块化的项目中使用,每个模块可以独立地使用SLF4J,而不会冲突。 SLF4J的API主要由以下部分组成: - **LoggerFactory**:它是获取日志器(Logger)的工厂类。通过`...
开发者通常会将此jar包添加到项目的类路径中,以便使用SLF4J的日志功能。 SLF4J API的核心接口是`org.slf4j.Logger`,它是所有日志操作的入口。通过`LoggerFactory.getLogger()`方法,开发者可以获取一个与当前类...
5. **日志适配器**:对于那些没有直接支持SLF4J的库,可以使用适配器(如`jul-to-slf4j.jar`,将Java Util Logging转换为SLF4J)。这样,整个应用程序的日志记录可以统一在SLF4J的控制之下。 6. **性能考虑**:由于...