大家好,我是头发多的阿星,今天跟大家聊一聊Java日志系统。Java日志系统可以说是五花八门,琳琅满目。导致很多小伙伴对日志标准库之间复杂的关系感到恼火。他们不知道统一系统的日志标准库需要依赖哪个jar包。百度搜了所谓的博客,照着别人照抄,但都看不懂原理,甚至还有长期做项目,jar冲突跑不起来的,还有他们的心态直接爆炸。咳咳,静下心来,别慌,阿星带你了解原理,只要你静下心来,跟着这篇文章,一键三连,日志标准库随便改,并统一日志输出。发展历程我们要正确配置日志,让jar之间相互生效,首先要理清关系,而理清关系,就要从它的发展历程说起。System.out和System.err在2001年之前,Java没有日志库,打印的日志都是基于System.out和System.err。我太愚蠢了,这太离谱了。缺点是:产生大量IO操作,生产环境无法合理控制是否需要输出。输出内容不能保存到文件,只能在控制台打印。定制化,而且日志粒度不够细Log4j这时候有个叫ceki的巨头站出来说你的不好用,我的好用,然后2001年拿出了Log4j,果然是比系统系列好。Log4j一度成为业界的日志标准。后来Log4j成为了Apache的项目,Ceki也加入了Apache组织(据说Apache还建议Sun将Log4j引入Java的标准库,被Sun拒绝了)。JUL(JavaUtilLogging)原来Sun也有自己的打算,不就是个日志吗,我自己也弄了一个。2002年2月,JDK1.是按照Log4j复制过来的,现在还没有复制。JDK1.5以后才在性能和易用性上有所提高。因为Log4j在JUL出来之前就已经成为成熟的技术,这使得Log4j在选型上有一定的优势。JCL(JakartaCommonsLogging)市面上有两种Java日志标准库,分别是Log4j和JUL。日志标准库实现了它的抽象接口,让你的日志操作都有一个统一的接口。所以在JUL出来没多久,Apache在2002年8月推出了JCL(JakartaCommonsLogging),也就是日志抽象层,支持运行时动态加载日志组件的实现,当然也提供了Simple的默认实现Log(在ClassLoader中搜索,如果能找到Log4j,则默认使用log4j实现,如果找不到,则使用JUL实现,如果找不到,则使用JCL提供的SimpleLog实现)。但是JUL有三个缺点:效率低,容易造成混乱。在使用自定义ClassLoader的程序中,使用JCL会造成内存泄漏。总之问题挺多的~Slf4j(SimpleLoggingFacadeforJava)2006年巨头Ceki(Log4j的作者)因为一些原因离开了Apache组织,后来Ceki觉得JCL不好用,于是开发了新的日志标准接口规范Slf4j(SimpleLoggingFacadeforJava),也可以称为日志门面。很明显,Slf4j就是标准的JCL,后来证明Slf4j优于JCL。由于Slf4j出来的晚,只有一个接口,没有实现的日志库也很蛋疼。比如JUL和Log4j都没有实现Slf4j,即使开发者想使用Slf4j。就在这时,巨人策奇开口了。Sum和Apache这两个组织不来实现我的接口也没关系。我会做。只有魔法才能战胜魔法。Ceki背后的巨头提供了一系列的桥接包来帮助Slf4j接口与其他日志库建立联系。这种方法称为桥接设计模式。有了桥接包的配合,其他问题就迎刃而解了。我们先来看看这些问题。从上图可以看出,不同时期的项目使用的日志标准库是不一样的。我们以Slf4j接口为分界线,考虑两个问题,Slf4j之前的项目如何统一日志标准,Slf4j之后的项目如何统一日志标准。先来看看Slf4j之后如何统一项目的日志标准。项目D和E都使用Slf4j接口。首先,在代码层统一了。统一日志标准也很简单。直接替换日志标准库和对应的桥接包就可以了,如下图,好家伙,Slf4j接口有了桥接包就无敌了,可以灵活配置。.看看Slf4j之前的项目是如何统一日志标准的。项目A、B、C都使用不同的日志标准,所以它们的API也不一样。要想统一标准,首先要改代码。这太过分了,不是吗?有没有办法在不改代码的情况下统一A、B、C项目的日志标准呢?当然有办法。Slf4j接口可以通过bridge包挂接具体的日志标准库。为什么log标准库不能通过bridge包挂接Slf4j接口?阿星想把A、B、C项目统一成Log4j日志输出,只需要做如下调整,是不是很简单,引入Slf4j和相关的桥接包,然后引入具体的日志标准库,比如Log4j,以及已完成3各项目统一日志标准,对代码层零侵入。LogbackCeki巨头认为市面上的日志标准库都是间接实现了Slf4j接口,也就是说每次都需要配合桥接包。因此,2006年Ceki巨头推出了基于Slf4j接口的Logback日志标准库作为Slf4j接口的默认实现,Logback也非常强大,在功能完整性和性能上超越了现有的所有日志标准库。目前Java日志系统的关系图如下:自从Log4j2从Logback出来后,可以说Slf4j+Logback的结合如火如荼,对JCL+Log4j的结合产生了极大的冲击。Apache很可能被Logback超越。2012年Apache直接上线了新项目Log4j2(不兼容Log4j),而Log4j2完全借鉴了Slf4j+Logback(抄袭嫌疑非常明显)。因为Log4j2不仅具有Logback的所有特性,而且有单独的设计,分为log4j-api和log4j-core,log4j-api是日志接口,log4j-core是日志标准库,Apache也提供了各种桥包。..至此,Java日志系统分为两大阵营,分别是Apache阵营和Ceki阵营,如下图所示。至于系统中使用的系统,您可以自行选择。阿星个人更喜欢使用Ceki提供的Slf4j。桥接包简介相信大家对桥接包都有一个基本的概念。这里阿星列出了Slf4j配合Slf4j切换到日志标准库slf4j-jdk14.jarSlf4j转JUL的桥接器slf4j-log4j12.jarSlf4j转Log4j的桥接器log4j-slf4j-impl.jar的桥接器Slf4j转Log4j2的桥接器ofslf4j-jcl.jarBridgeofSlf4jtoJCL一些实际的日志框架转向Slf4jjul-to-slf4j.jarBridgeofJULtoSlf4jlog4j-over-slf4j.jarBridgeofLog4jtoSlf4jjcl-over-slf4j.jarJCLtoSlf4j桥接小实践从事Java开发的小伙伴都知道,Spring框架内部使用JCL作为日志输出标准,但是项目中使用的是Slf4j+Logback作为日志输出标准。问题来了,如何让项目中的Spring保持统一的日志输出标准呢?其实很简单。只需要引入正确的Slf4j桥接包,去掉无用的日志组件即可。阿星没有骗你,引入jcl-over-slf4j.jar或者jul-to-slf4j.jar就解决了,很简单~总结本文到此结束,以上,阿星通过了Java日志发展史一步步带你理清Java日志之间的关系,提出问题,解决问题。相信看完之后,你不会再为日志标准库之间复杂的关系所困扰,也会知道统一日志标准的缘由。.关于我我是阿星,一个热爱技术的Java程序员,公众号「编程阿星」会定期分享操作系统、计算机网络、Java、分布式、数据库等方面的优质原创文章。在2021,在BeBetter的路上与您共同成长!非常感谢兄弟姐妹们能够看到这里。原创并不容易。如果文章有帮助,可以关注,点赞,分享,评论,都是支持(不想当妓女)!希望你我都能走上自己想走的路,下篇文章见
