背景
java的日志体系是一个比较复杂的体系,它有很多日志组件,他们之间是什么关系?如何来配置?今天让我们来揭开它的面纱。
常用日志框架
log4j
logback
log4j2
java.util.logging(jul)
为什么会有JCL和slf4j?
问题:如果你要设计一个框架,如spring,mybatis等,那么你怎么来设计日志模块?应该选择哪个组件?
回答:以上都不能选,如果你选择了log4j,但是项目用了logback作为日志输出,那么别人就没办法使用你的框架了,这样框架的通用性就不好。设计框架日志模块只能根据项目实际使用什么日志框架来动态的加载日志框架。目前有Apache Commons Logging(JCL)、slf4j两种方案。
JCL
原理:
本身只提供日志接口,它在项目启动的时候,动态的去绑定日志框架。
缺陷:由于它使用了ClassLoader寻找和载入底层的日志组件, 导致像OSGI这样的框架无法正常工作,由于其不同的插件使用自己的ClassLoader。OSGI的这种机制保证了插件互相独立,然而却使Apache Common Logging无法工作。
图表示:jcl与各日志组件的关系
slf4j
原理:
本身也只提供日志接口,通过静态的方式来绑定日志框架,主要是把相应的jar包加入到classPath来完成集成。如果你需要使用logback组件,那么你需要引入logback相应的jar包和桥接器jar,这样就可以使用logback日志了。使用其他日志组件也是一样的。
图表示:slf4j与各日志组件的关系
表格列出桥接器和相应的日志组件:
桥接器 | 对应日志组件 |
---|---|
slf4j-log4j12.jar | log4j |
slf4j-jdk14.jar | java.util.logging(jul) |
slf4j-jcl.jar | jcl |
log4j-slf4j-impl | log4j2 |
logback-classic | logback |
如果绑定了多个桥接器,那么会出现下面的提示。但是不会报错,它会使用最先引入的桥接器。后面的桥接器配置都不会生效。
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/E:/worksoft/repository/ch/qos/logback/logback-classic/1.2.2/logback-classic-1.2.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/E:/worksoft/repository/org/slf4j/slf4j-log4j12/1.7.21/slf4j-log4j12-1.7.21.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
jcl和slf4j如何同时使用?
问题:老项目中使用了jcl,如spring是使用jcl的,现在又要使用slf4j,那么如何来做?
回答:可以引入jcl-over-slf4j的jar包,他是桥接器,可以把jcl指向slf4j。如果不统一会打印两份日志。
图表示:原jcl中使用slf4j
图表示:原log4j中使用slf4j
图表示:原jul中使用slf4j
日志组件到slf4j的桥接器
日志组件 | 桥接器 |
---|---|
log4j | log4j-over-slf4j |
jul | jul-to-slf4j |
jcl | jcl-over-slf4j |
堆栈溢出问题
死循环,会出现堆栈溢出的问题。
SLF4J: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
项目地址:
https://gitee.com/ccgx/java-example/tree/master/log
示例包括各个组件的使用,slf4j,jcl的使用等。
注意:本文归作者所有,未经作者允许,不得转载