做为后端开发,日志多是咱们最经常使用的功能之一了。平时你们也可能常常碰见日志冲突,常见的overflow报错,今天为你们详解一下,这其中的原理以及问题所在。本文涉及 jar 包有:log4j,log4j-over-slf4j,slf4j-api,slf4j-log4j12 等等。java
不知道你们在平时开发中,是否常常碰见如下几个问题:后端
什么是 SLF4J 呢?简而言之,他就是一个日志的门面,市场上的日志系统很是多, SLF4J 想作的一件事情,就是将这多种的日志系统包装起来,提供统一的 API 供调用,从而解决日志的列国争霸的状况。api
在解决以上问题以前,让咱们先对日志系统作一个大概的理解。到底什么是 log4j,什么是 slf4j-api,为何有一个 slf4j-log4j12,又怎么有个log4j-over-slf4j,看上去头晕眼花,绕来绕去。先祭上一张官网图:app
第1个顾名思义,不绑定,就是没有日志实现。第5,6能够看出来,是 SLF4J 本身的实现,这里就忽略不讲。因此着重讲一下二、三、4。他们有个共同的特色,就是他们都是日志的真正实现库,他们和SLF4J没有关系,你可使用 logback 打印日志,也可使用 log4j 打日志。jvm
第一层, application 就是应用层。日志
看看图中第二层,通通都是 SLF4J API。那么这一层是干什么用的呢?这一层就是一个门面层,而和门面层息息相关的 jar 包是什么呢?对,就是图中的 slf4j-api.jar 。这个jar包中,提供了日志调用的全部接口,应用都是直接调用这个 jar 包中的接口进行日志调用。code
第三层有点不一样。第一列,无实现,第2,5,6都是原生的一个实现,而3,4都有一个适配层。这里说说 logback。logback 他为何不须要适配层呢,由于他就是按照了 SLF4J 接口去实现的一个日志库,至关于亲儿子,天然不须要适配层。因此,logback-classic.jar 和 logback-core.jar 就是 logback 的底层实现。而3,4就不一样了,他们的接口或多或少会有差别,调用方式也各不相同,因此,须要一个适配层。因此 slf4j-log412.jar 和 slf4j-jdk14.jar 包的做用就是一个适配,这里是一个桥接,应用经过 slf4j-api 的接口调用过来时,桥接类实际会调用其底层的实现,达到一个桥接的过程。因此,slf4j-log412.jar,slf4j-jdk14.jar,slf4j-simple.jar,slf4j-nop.jar 是同一类,就是把-
右边的实现进行一个桥接。cdn
第四层,能够看到第2,3对应的实现,log4j.jar 和 jvm 就是最后的实现。blog
至此,作一个小总结:接口
此时再看看上面那张图,是否已经所有理解了呢?
若是看完上面,不以为 SLF4J 有什么好处,就来看看下面这张图:
着重讲解左上角这一部分,其余的相似。
先看 application,这个是应用,能够看到,他也遇到了我说到的问题。他的依赖里面有使用 log4j 的,有用 commons logging 的,有用 java.util.logging 的。因此此时须要作一个替换,分别是经过 jcl-over-slf4j.jar 替换掉 commons-logging.jar,log4j-over-slf4j.jar 替换掉 log4j.jar, jul-to-slf4j.jar 包中安装 SLF4JBrindgeHandler 解决。替换掉以后,就把全部日志调用转接到 slf4j-api 上了,而后 api 接口再调用底层实现,图上是 logback。文中说的替换是什么意思呢?就是把原日志实现库排除掉,引入 xxx-over-slf4j.jar 。
那么,xxx-over-slf4j.jar 是什么原理呢?先给你们看这张图:
再看其余两个图,底层分别是 log4j, jvm 实现。都是讲其余库 over 一下到 slf4j 。
特别注意一下, logback 不须要转,为何?由于他是亲儿子。天生就带这些。
因此再小总结一下:
-
前的太子用 slf4j 的狸猫代替。而 xxx-to-slf4j.jar 比较特殊,这是由于 xxx 这个包没法被替换掉,好比 java.util.logging,系统的库,没法替换,因此只能采用别的手段。此类别的实现读者有兴趣能够去看看,本文再也不分析。为何会出现这个问题呢?控制台输出上通常会比较清楚,就是你既使用了桥接库,又使用了over库(狸猫)。好比:
上面提到的这个错误:
其余问题都比较相似,若是看懂了上文的介绍,应该能够着手解决此类问题了。
了解了日志的原理,之后妈妈不再担忧日志冲突了!