介绍
推荐找篇文章
Log大的体系结构
java的日志体系略微复杂, 不但涉及到各个日志组件,还涉及到各个日志组件之间的桥接, 理解起来略微困难.
所以我们分层来看. 上图.
第一层:业务访问层, 业务上层使用各种Log的API: JDK的logging, slf4j, apache的common-logging,
第二层:标准日志接口层:slf4j,
第三层:日志实现层: 还是那四个组件.
第二层是否可以有其他接口, 可以,但是我理解slf4j 基本成为事实标准,所以所有的桥接都向slf4j看齐. 这样,能减少复杂度.
桥接器介绍
接口桥接器
- jul-to-slf4j:jdk-logging到slf4j的桥梁
- log4j-over-slf4j:log4j1到slf4j的桥梁
- jcl-over-slf4j:commons-logging到slf4j的桥梁
举例:比如使用log4j的API进行编程,但最终用logback来进行输出,所以就需要先将log4j1的日志输出转交给slf4j来输出,slf4j再交给logback来输出。这就是log4j-over-slf4j做的事
实现桥接器
- slf4j-jdk14:slf4j到jdk-logging
- slf4j-log4j12:slf4j到log4j1
- log4j-slf4j-impl:slf4j到log4j2
- logback-classic:slf4j到logback
- slf4j-jcl:slf4j到commons-logging
各组件介绍
common-logging
apache的common-logging,动态查找原理
slf4j
Simple Logging Facade for JAVA
静态绑定,只有接口定义
LogBack
log4j的升级版本
logback-core
logback- classic
logback-access
冲突问题
看官方文档
jcl-over-slf4j 与 slf4j-jcl 冲突
- jcl-over-slf4j: commons-logging切换到slf4j
- slf4j-jcl : slf4j切换到commons-logging
死循环, 内存溢出.
log4j-over-slf4j 与 slf4j-log4j12 冲突
- log4j-over-slf4j : log4j1切换到slf4j
- slf4j-log4j12 : slf4j切换到log4j1
死循环, 内存溢出.但是内部代码有判断逻辑, 解决了这个问题, 会提示
org.apache.log4j.Log4jLoggerFactory
// check for delegation loops
static {
try {
Class.forName("org.slf4j.impl.Log4jLoggerFactory");
String part1 = "Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError. ";
String part2 = "See also " + LOG4J_DELEGATION_LOOP_URL
+ " for more details.";
Util.report(part1);
Util.report(part2);
throw new IllegalStateException(part1 + part2);
} catch (ClassNotFoundException e) {
// this is the good case
}
}
jul-to-slf4j 与 slf4j-jdk14 冲突
- jul-to-slf4j : jdk-logging切换到slf4j
- slf4j-jdk14 : slf4j切换到jdk-logging
其他
可能产生死循环
Component
|
| log to Apache Commons Logging
V
jcl-over-slf4j.jar — (redirect) —> SLF4j —> slf4j-log4j12-version.jar —> log4j.jar —> 输出日志
同时配置了 log4j-over-slf4j.jar 和 slf4j-log4j12-version.jar 会发生什么情况呢?没错,日志会被踢来踢去,最终进入死循环.
tomcat控制
access日志:通过server.xml 的AccessLogValve来控制