slf4j优于log4j

之前已经写过以前简要的《log4j》,讲述了log4j的配置及使用。现在来说说slf4j优于log4j的几个点。先说结论吧:请尽量使用slf4j。

1.依赖抽象而不是依赖具体实现

slf4j对比Log4J,logback和java.util.Logging,slf4j是接口,其他都是具体的实现类。当客户端调用slf4j打印日志的时候,将通过Log4jLoggerAdapter这样一个log4j的适配器调用log4j的实现。SLF4J不同于其他日志类库,与其它有很大的不同。SLF4J(Simple logging Facade for Java)不是一个真正的日志实现,而是一个抽象层( abstraction layer),它允许你在后台使用任意一个日志类库。如果是在编写供内外部都可以使用的API或者通用类库,那么你真不会希望使用你类库的客户端必须使用你选择的日志类库。

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

总的来说,SLF4J使你的代码独立于任意一个特定的日志API,这是一个对于开发API的开发者很好的思想。


2.编码及性能

SLF4J API有一个很优秀的特性,被称为占位符(place holder),在代码中表示为“{}”的特性。占位符是一个非常类似于在String的format()方法中的%s,因为它会在运行时被某个提供的实际字符串所替换。这不仅降低了你代码中字符串连接次数,而且还节省了新建的String对象。即使你可能没需要那些对象,但这个依旧成立,取决于你的生产环境的日志级别,例如在DEBUG或者INFO级别的字符串连接。因为String对象是不可修改的并且它们建立在一个String池中,它们消耗堆内存( heap memory)而且大多数时间他们是不被需要的,例如当你的应用程序在生产环境以ERROR级别运行时候,一个String使用在DEBUG语句就是不被需要的。通过使用SLF4J,你可以在运行时延迟字符串的建立,这意味着只有需要的String对象才被建立。而如果你已经使用log4j,那么你已经对于在if条件中使用debug语句这种变通方案十分熟悉了,但SLF4J的占位符就比这个好用得多。

先来对比一下log4j和slf4j的代码:

//log4j
if (logger.isInfoEnabled()){
    logger.info("arg1:"+arg1+" , arg2:"+arg2);
}
//slf4j
logger.info("参数一:{},参数二:{}", arg1, arg2);
//slf4j-ap1 1.7以上版本支持3个以上参数
logger.info("参数一:{},参数二:{},参数三:{},参数四:{}", arg1, arg2, arg3, arg4);
做次比较,显而易见使用slf4j的代码更加简洁。

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

public void info(String format, Object arg1, Object arg2) {
  if (logger.isInfoEnabled()) {
    FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
    logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable());
  }
}
值得一提的是,在我们的应用程序中日志是不可或缺的一部分,但同时,日志也会对性能产生影响。因此,在我们的项目中,只进行必要的日志记录就好。


3.依赖jar包

使用slf4j需要slf4j-api包,同时还需要结合自己具体实现引入相应的jar包。例如本身使用的log4j的话,还需要依赖slf4j-log4j12这个包。

<!-- slf4j  -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.5</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.5</version>
</dependency>
理论上slf4j-log4j12这个包中已经包含了slf4j-api和log4j的jar包,但是一个复杂的项目中往往多个依赖包中会出现不同版本的log4j等jar包,具体jar包是否出现冲突,或者版本使用是否正确还需要自行在项目中检查。


总结
1.在你的开源或内部类库中使用SLF4J会使得它独立于任何一个特定的日志实现,这意味着不需要管理多个日志配置或者多个日志类库,你的客户端会很感激这点。

2.SLF4J提供了基于占位符的日志方法,这通过去除检查isDebugEnabled(), isInfoEnabled()等等,提高了代码可读性。

3.通过使用SLF4J的日志方法,你可以延迟构建日志信息(Srting)的开销,直到你真正需要,这对于内存和CPU都是高效的。

4.作为附注,更少的暂时的字符串意味着垃圾回收器(Garbage Collector)需要做更好的工作,这意味着你的应用程序有为更好的吞吐量和性能。




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值