SLF4J 和 Log4j2

目录


1.背景介绍

SLF4J是怎么诞生的?
很久很久以前,Apache说服log4j以及其他的日志按照commons-logging的标准编写,但是由于commons-logging的类加载器有点问题,实现起来也不友好,因此log4j的作者创作了SLF4J,也因此与commons-logging平分天下。到底使用哪一个,由开发者自己决定。

SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。 如果一个项目已经使用了log4j,而你加载了一个类库,比方说 Apache Active MQ——它依赖于于另外一个日志类库logback,那么你就需要把它也加载进去。但如果Apache Active MQ使用了SLF4J,你可以继续使用你的日志类库而无语忍受加载和维护一个新的日志框架的痛苦。 从设计模式的角度考虑,它是用来在log和代码层之间起到门面的作用。对用来来说只要使用slf4j提供的接口,即可隐藏日志的具体实现。这与jdbc和相似。使用jdbc也就避免了不同的具体数据库。使用了slf4j可以对客户端应用解耦。因为当我们在代码实现中引入log日志的时候, 用的是接口,所以可以实时的更具情况来调换具体的日志实现类。这就是slf4j的作用。
2.知识剖析

1)SLF4J到底是什么?

SLF4J(Simple Loging Facade For Java)即它仅仅是一个为Java程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就比如JDBC一样,只是一种规则而已。所以单独的slf4j是不能工作的,必须搭配其他具体的日志实现方案,比如apache的org.apache.log4j.Logger,jdk自带的java.util.logging.Logger等等 commons-logging和slf4j都是日志的接口,供用户使用,而没有提供实现。log4j、logback、java.logging才是日志的真正实现。当我们调用接口时,接口的工程会自动寻找恰当的实现,返回一个实现的实例。

2)SLF4J的实现原理什么?
我们自己的系统中使用了logback这个日志系统
我们的系统使用了A.jar,A.jar中使用的日志系统为log4j
我们的系统又使用了B.jar,B.jar中使用的日志系统为slf4j-simple

这样,我们的系统就不得不同时支持并维护logback、log4j、slf4j-simple三种日志框架,非常不便。

解决这个问题的方式就是引入一个适配层,由适配层决定使用哪一种日志系统,而调用端只需要做的事情就是打印日志而不需要关心如何打印日志,slf4j或者commons-logging就是这种适配层,slf4j是本文研究的对象。

从上面的描述,我们必须清楚地知道一点:slf4j只是一个日志标准,并不是日志系统的具体实现。理解这句话非常重要,slf4j只做两件事情:

  • 提供日志接口
  • 提供获取具体日志对象的方法

slf4j-simple、logback都是slf4j的具体实现,log4j并不直接实现slf4j,但是有专门的一层桥接slf4j-log4j12来实现slf4j。

为了更理解slf4j,我们先看例子,再读源码,相信读者朋友会对slf4j有更深刻的认识


3.常见问题

1)Log4j怎么结合SLF4J?


2)Log4j结合SLF4J有什么优势?

4.解决方案

A.添加SLF4J的jar包


B.添加适配器jar包:slf4j-log4j12


tip:实际只添加适配器jar包就可以了。

2)Log4j结合SLF4J有什么优势?


有数据表明,一个应用程序中大约有4%的代码用来打日志。在代码中,我们经常需要把一些参数作为Debug级别的日志打印出来,方便我们进行调试。项目部署之前我们会把日志的级别调到INFO,项目正式运转的时候就不会打印Debug级别的日志。


但Log4j在这方面做的不太好,用到了isDebugEnable()并在项目刚运行时就拼接字符串存到内存里,这样不仅检查了两次日志级别,并占用了内存资源,导致性能比其他日志实现要差。这种操作会使得我们的代码看起来更像是在打日志而不是在实现某种功能。
通过结合SLF4J,Log4j也可使用参数替代字符串拼接,这样只会检查一次日志级别,且只在需要输出日志的时候才会拼接字符串。代码更优雅、性能也有提升。


5.编码实战

1)Log4j结合SLF4J


2)Log4j结合SLF4J前后的性能对比


3)Log4j2怎么使用


4)Log4j和Log4j2的性能对比

6.扩展思考

1)为什么要以类名作为logger的名字?


首先我们要知道,类通常以类代表的对象或者类可以实现的功能来命名,这种命名方式提高了可读性,易于他人 识别。同样的,以类名作为logger的名字可以快速定位产生日志的类,还可以更精确地对每个类的日志级别、输出目的地和输出样式进行调整。
这种命名方式实际有什么作用呢?


A.同名Logger


B.父类Logger


C.Root Logger


2)LOG4J 怎么迁移到 LOG4J2?
A.前提条件


没有调用Log4j-1.x的内部方法,比如Appenders(),LoggerRepository()


没有使用代码的方式配置Log4j


没有调用DOMConfigurator或PropertyConfigurator这两个类


B.替换jar包


把 Log4j-1.x.jar 换成 log4j-1.2-api.jar(这个jar包内有log4j-api、log4j-core两个jar包)
C.修改代码


首先要清楚,jar包前缀不一样,版本1是org.apache.log4j,版本2是org.apache.logging.log4j


a.版本1是Logger.getLogger( ),改成版本2的LoggerManager.getLogger( )


b.版本1是Logger.getRootLogger( ),改成版本2的LoggerManager.getRootLogger( )
D.配置文件


log4j.properties换成log4j2.xml


7.参考文献

参考一:Log4j2 官网


参考二:Log4j 迁移到 Log4j2


参考三:Log4j2 高级配置以及简单的示例


参考四:SLF4J 官网



8.更多讨论

猜你喜欢

转载自blog.csdn.net/qq_42224273/article/details/80666033