log4j, common-logging, slf4j 关系
最近因为项目原因,认真学习了一下 log4j 相关内容,主要是从网上找资料,以及追踪原代码。
关于如何使用,网上有很多资料,这里不做具体介绍。下面介绍一下这些工具的关系。
log4j 是最强大和流行的日志工具,同时又有很多其他的日志工具,比如 logback(据说比log4j 更优秀,由同一班人马打造), java.util.logging.Logger 等。为了统一各种各样的日志工具,common-logging 出现了,下面是它所有的源代码文件:
![](https://images2015.cnblogs.com/blog/236580/201511/236580-20151128193249234-2042036407.png)
结构明了:
1、Log 定义了统一的抽象接口
2、impl 中封装了已有的多种日志工具,比如 Log4JLogger 是对 log4j 的封装,Jdk14Logger 是对 java.util.logging.Logger 的封装, AvalonLogger/LogKietLogger 是另外日志工具的封装。最后 SimpleLog 是 common-logging 自己实现的 Logger,功能简单,是其他工具不能使用时的最终方案。
3、LogFactory 是对外的接口,使用方式为:LogFactory.getLog(Test.class)。默认实现为图中的 LogFactoryImpl。
slf4j 与上面的 common-logging 功能和定位相似,由一个基础的包 slf4j-api 定义了统一的日志接口 Logger,工厂接口 LoggerFactory。包 slf4j-log4j12 是 slf4j 对 log4j(1.2版本?) 的封装,其中 Log4jLoggerAdapter 包装了 org.apacha.log4j.Logger,继承于org.slf4j.Logger,Log4jLoggerFactory 是相应的工厂方法。这里两个 jar 包需要一起使用。
![](https://images2015.cnblogs.com/blog/236580/201511/236580-20151128193326921-371231284.png)
我们的项目里,是一种更加纠结的情况,三者都存在,具体是 slf4j 实现了 common-logging 的两个接口,即下图中 SLF4JLog 实现了 org.apache.commons.logging.Log,工厂方法 SLF4jLogFactory 继承了 org.apache.commons.logging.LogFactory。
![](https://images2015.cnblogs.com/blog/236580/201511/236580-20151128193410999-886580922.png)
个人觉得这样过于复杂,没有必要,不知道能够移除对 slf4j 的依赖。
关于 log4j,默认的配置文件是 log4j.properties(或者 log4j.xml,但我不太喜欢用)。引用的一些 jar 包常常已经包含了该文件(差评),有可能覆盖我们自己的配置文件,需要手工移除。当然也可以使用系统变量 log4j.configuration 指定配置文件地址,而不是使用默认文件地址。
commons-logging 有个默认的配置文件commons-logging.properties,该文件可有可无,这是其方便之处。其中可以设置变量 priority,解决了多个配置文件的选择问题。我觉得,如果可以在 commons-logging.properties 里面也设置 log4j.configuration 这样的属性,使其生效就完美了。然而,并没有。