Java各类日志组件分析汇总

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

  只使用java.util.logging.Logger

最简单的场景,正式系统一般不会这么用,自己写点小demo、测试用例啥的是可以这么用。不要任何第三方依赖,jdk原生支持。

  只使用Apache Commons Logging

需要引入commons-logging包,示例如下:

commons-logging commons-logging 1.2

  Apache Commons Logging和log4j结合使用

需要引入commons-logging包和log4j包,示例如下:

commons-logging commons-logging 1.2 log4j log4j 1.2.17

该模式下可以使用的打点api:

  • org.apache.commons.logging.Log,commons-logging里的api;

  • org.apache.log4j.Logger,log4j里的api;

无论使用哪种api打点,最终日志都会通过log4j进行实际的日志记录。推荐用commons-logging里的api,如果直接用log4j里的api,就跟单用log4j没区别,就没有再引入commons-logging包的必要了。

既然最终是通过log4j实现日志记录,那么日志输出的level、target等也就是通过log4j的配置文件进行控制了。下面是一个log4j配置文件《log4j.properties》的简单示例:

#log4j.rootLogger = error,consolelog4j.logger.com.suian.logtest = trace,console

#输出源console输出到控制台log4j.appender.console = org.apache.log4j.ConsoleAppenderlog4j.appender.console.Target = System.outlog4j.appender.console.layout = org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss,SSS} [%t] %-5p %c - [log4j]%m%n

既然是推荐使用commons-logging里的api打点,为了能找到log4j的日志实现,必须通过《commons-logging.properties》配置文件显式的确定关联,示例如下:

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

代码中使用JCL api进行日志打点,底层使用log4j进行日志输出。日志输出控制依托于log4j的配置文件,另外需要在commons-logging.properties配置文件中显式指定与log4j的绑定关系。
  单独使用log4j
这个是早几年最最流行的用法了,现在因为log4j本身的问题以及新的日志框架的涌现,已经逐步退出历史舞台了。具体怎么用自己去百度吧。
  SLF4J结合Logback
当下最流行的用法,SLF4J为使用场景最广泛的日志门面,加上Logback的天然实现,简单、统一、快速。
需要引入第三方依赖:

org.slf4j slf4j-api s l f 4 j . v e r s i o n < / v e r s i o n > < / d e p e n d e n c y > < d e p e n d e n c y > < g r o u p I d > c h . q o s . l o g b a c k < / g r o u p I d > < a r t i f a c t I d > l o g b a c k − c o r e < / a r t i f a c t I d > < v e r s i o n > {slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version> slf4j.version</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logbackcore</artifactId><version>{logback.version} ch.qos.logback logback-classic ${logback.version}

  单独使用Log4j2

Log4j2感觉就是SLF4J+Logback。log4j-api等价于SLF4J,log4j-core等价于Logback。

需要引入第三方依赖:

org.apache.logging.log4j log4j-api 2.6.2 org.apache.logging.log4j log4j-core 2.6.2

冲突处理

理论上各种日志输出方式是可以共存的,比如log4j和log4j2以及logback等,但是麻烦的是我们得维护多个配置文件,必须充分了解每个组件使用的是那种日志组件,然后进行对应的配置文件配置。

如何解决呢?每一个想做通用日志解决方案的,都对兼容性问题进行了特殊处理。目前只有slf4j和log4j2提供了这样的整合机制,其他的基本都很弱。

代码中可能使用的日志打点Api列举:

  • java.util.logging.Logger,jdk自带的;

  • org.apache.commons.logging.Log,commons-logging包里的api;

  • org.apache.log4j.Logger,log4j包里的api;

  • org.apache.logging.log4j.Logger,log4j2提供的api,在log4j-api包里;

  • org.slf4j.Logger,slf4j提供的api,在slf4j-api包里;

上述打点方式,在一个应用中是有可能共存的,即使自己写的代码可以确保都使用同一类api,但是引入的第三方依赖里就可能各式各样了。该怎么处理呢?

前面已经提过了,现在能够对各类冲突支持比较到位的就是slf4j和log4j2,他们都提供了很多的绑定器和桥接器。

  • 所谓的绑定器,也可以称之为适配器或者包装类,就是将特定api打点的日志绑定到具体日志实现组件来输出。比如JCL可以绑定到log4j输出,也可以绑定到JUL输出;再比如slf4j,可以通过logback输出,也可以绑定到log4j、log4j2、JUL等;

  • 所谓的桥接器就是一个假的日志实现工具,比如当你把 jcl-over-slf4j.jar 放到 CLASS_PATH 时,即使某个组件原本是通过 JCL 输出日志的,现在却会被 jcl-over-slf4j “骗到”SLF4J 里,然后 SLF4J 又会根据绑定器把日志交给具体的日志实现工具。

slf4j整合日志输出

  java.util.logging.Logger

将JUL日志整合到slf4j统一输出,需要引入slf4j提供的依赖包:

org.slf4j jul-to-slf4j 1.7.22

只引入依赖并不能整合JUL日志,该包里只是提供了一个JUL的handler,仍旧需要通过JUL的配置文件进行配置,slf4j绑定器(如logback)上设置的日志级别等价于JUL handler上的日志级别,因此控制JUL的日志输出,日志级别仍旧分两个地方控制:JUL配置文件《logging.properties》和slf4j绑定器的配置文件,比如《logback.xml》、《log4j2.xml》等。
  • 建立jdk14-logger的配置文件《logger.properties》,加入handler配置以及日志级别配置;

handlers= org.slf4j.bridge.SLF4JBridgeHandler.level= ALL

  • 在启动程序或容器的时候加入JVM参数配置-Djava.util.logging.config.file = /path/logger.properties;当然也可以使用编程方式进行处理,可以在main方法或者扩展容器的listener来作为系统初始化完成;此种方式有些场景下不如配置JVM参数来的彻底,比如想代理tomcat的系统输出日志,编程方式就搞不定了。
  org.apache.commons.logging.Log
将JCL日志整合到slf4j统一输出,需要引入slf4j提供的依赖包:

org.slf4j jcl-over-slf4j 1.7.22

jcl-over-slf4j包里所有类的根路径为org.apache.commons.logging,也有Log和LogFactory类,相当于以重写commons-logging包的代价来实现对JCL的桥接。Log与commons-logging包里的一模一样,LogFactory的实现,代码写死使用的是org.apache.commons.logging.impl.SLF4JLogFactory。
commons-logging包里默认使用的是org.apache.commons.logging.impl.LogFactoryImpl。以这样的代价来实现桥接,可以实现无缝对接,不像JUL那样还得添加额外配置,但是有一个坏处就是需要处理类库冲突了。commons-logging包和jcl-over-slf4j包肯定是不能共存的,需要将commons-logging包在classpath里排掉。
题外话,因为JCL本身就支持通过配置文件《commons-logging.properties》绑定适配器,所以个人感觉更倾向于封装一个适配器的方式来支持,就像commons-logging包里的org.apache.commons.logging.impl.Log4JLogger,这样更符合程序员的思维,明明白白。
桥接包的命名也是很讲究的,覆写的这种,命名为xxx-over-slf4j,如本例的jcl-over-slf4j;纯桥接的,命名为xxx-to-slf4j,如文章前面提到的jul-to-slf4j。
▐  org.apache.log4j.Logger

将log4j日志整合到slf4j统一输出,需要引入slf4j提供的依赖包:

org.slf4j log4j-over-slf4j 1.7.22

看桥接包的名字就知道了,log4j-over-slf4j肯定是覆写了log4j:log4j包,因此使用起来只需要引入依赖即可,不需要其他额外的配置。但是仍旧是要处理冲突的,log4j包和log4j-over-slf4j是不能共存的哦。
  org.apache.logging.log4j.Logger

将log4j2日志整合到slf4j统一输出,slf4j没有提供桥接包,但是log4j2提供了,原理是一样的,首先引入log4j2的桥接包:

org.apache.logging.log4j log4j-to-slf4j 2.6.2

log4j2提供的依赖包有org.apache.logging.log4j:log4j-api和org.apache.logging.log4j:log4j-core,其作用看包名就清楚了。log4j-core是log4j-api的标准实现,同样log4j-to-slf4j也是log4j-api的一个实现。

log4j-to-slf4j用于将log4j2输出的日志桥接到slf4j进行实际的输出,作用上来讲,log4j-core和log4j-to-slf4j是不能共存的,因为会存在两个log4j2的实现。

经测试,就测试结果分析,共存也是木有问题的,何解?log4j2加载provider的时候采用了优先级策略,即使找到多个也能决策出一个可用的provider来。在所有提供log4j2实现的依赖包中,都有一个META-INF/log4j-provider.properties配置文件,里面的FactoryPriority属性就是用来配置provider优先级的,幸运的是log4j-to-slf4j(15)的优先级是高于log4j-core(10)的,因此测试结果符合预期,log4j2的日志桥接到了slf4j中进行输出。

同样,为确保系统的确定性,不会因为log4j2的provider决策策略变更导致问题,建议还是要在classpath里排掉log4j-core,log4j2也是推荐这么做的。

log4j2整合日志输出


  java.util.logging.Logger

将JUL日志整合到log4j2统一输出,需要引入log4j2提供的依赖包:

org.apache.logging.log4j log4j-jul 2.6.2

log4j2整合JUL日志的方式与slf4j不同,slf4j只是定义了一个handler,仍旧依赖JUL的配置文件;log4j2则直接继承重写了java.util.logging.LogManager。

使用时,只需要通过系统属性java.util.logging.manager绑定重写后的LogManager(org.apache.logging.log4j.jul.LogManager)即可,感觉比slf4j的方式要简单不少。

  org.apache.commons.logging.Log

将JCL日志整合到log4j2统一输出,需要引入log4j2提供的依赖包:

org.apache.logging.log4j log4j-jcl 2.6.2

基于log4j-jcl包整合JCL比较简单,只要把log4j-jcl包扔到classpath就可以了。看起来slf4j的整合方式优雅多了,底层原理是这样的:JCL的LogFactory在初始化的时候,查找LogFactory的具体实现,是分了几种场景的,简单描述如下:

  1. 首先根据系统属性org.apache.commons.logging.LogFactory查找LogFactory实现类;

  2. 如果找不到,则以SPI方式查找实现类,META-INF/services/org.apache.commons.logging.LogFactory;log4j-jcl就是以这种方式支撑的;此种方式必须确保整个应用中,包括应用依赖的第三方jar包中,org.apache.commons.logging.LogFactory文件只有一个,如果存在多个的话,哪个先被加载则以哪个为准。万一存在冲突的话,排查起来也挺麻烦的。

  3. 还找不到,则读取《commons-logging.properties》配置文件,使用org.apache.commons.logging.LogFactory属性指定的LogFactory实现类;

  4. 最后再找不到,就使用默认的实现org.apache.commons.logging.impl.LogFactoryImpl。

  org.apache.log4j.Logger

将log4j 1.x日志整合到log4j2统一输出,需要引入log4j2提供的依赖包:

org.apache.logging.log4j log4j-1.2-api 2.6.2

log4j2里整合log4j 1.x日志,也是通过覆写log4j 1.x api的方式来实现的,跟slf4j的实现原理一致。因此也就存在类库冲突的问题,使用log4j-1.2-api的话,必须把classpath下所有log4j 1.x的包清理掉。

  org.slf4j.Logger

将slf4j日志整合到log4j2统一输出,需要引入log4j2提供的依赖包:

org.apache.logging.log4j log4j-slf4j-impl 2.6.2

log4j-slf4j-impl基于log4j2实现了slf4j的接口,其就是slf4j-api和log4j2-core之间的一个桥梁。这里有个问题需要注意下,务必确保classpath下log4j-slf4j-impl和log4j-to-slf4j不要共存,否则会导致事件无止尽地在SLF4J和Log4j2之间路由。

日志打点API绑定实现


slf4j-api和log4j-api都是接口,不提供具体实现,理论上基于这两种api输出的日志可以绑定到很多的日志实现上。slf4j和log4j2也确实提供了很多的绑定器。简单列举几种可能的绑定链:

  • slf4j → logback

  • slf4j → slf4j-log4j12 → log4j

  • slf4j → log4j-slf4j-impl → log4j2

  • slf4j → slf4j-jdk14 → jul

  • slf4j → slf4j-jcl → jcl

  • jcl → jul

  • jcl → log4j

  • log4j2-api → log4j2-cor

  • log4j2-api → log4j-to-slf4j → slf4j

来个环图:

手淘行业与智能运营团队

在阿里,如果不经历电商,那么你可能就失去了一半的工作乐趣;做电商,如果不搞商业智能,那么你可能就失去了链接人、货、场、商,给几亿用户创造更美好生活的机会!但是现在,一个充满乐趣和机会的岗位就摆在你的面前 —— 它就是,行业与智能运营团队,电商中最智能的技术团队!大家走过路过,不要错过!我们要从上到下打造一支幸福感极强的团队 —— 如果你在追求幸福感,找我们,没毛病!未来已来,淘系技术部行业与智能运营团队,这支即将成为阿里最具幸福感的技术团队,期待具有好奇心和思考力的你的加入!

就是现在,阿里巴巴淘系技术部行业与智能运营团队,Java工程师、技术专家、架构师面向社会+校园招聘,base杭州阿里巴巴西溪园区!

投喂简历给我们:mingkai.wmk@alibaba-inc.com

✿  拓展阅读

《MySql面试专题》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

《MySql性能优化的21个最佳实践》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

《MySQL高级知识笔记》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

文中展示的资料包括:**《MySql思维导图》《MySql核心笔记》《MySql调优笔记》《MySql面试专题》《MySql性能优化的21个最佳实践》《MySq高级知识笔记》**如下图

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

关注我,点赞本文给更多有需要的人
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
03)]

[外链图片转存中…(img-UAQ1TSQP-1714679925904)]

[外链图片转存中…(img-8iYqxfG2-1714679925904)]

[外链图片转存中…(img-mcTjXYO6-1714679925904)]

[外链图片转存中…(img-2l4FtOTO-1714679925905)]

[外链图片转存中…(img-AZeArXHa-1714679925905)]

[外链图片转存中…(img-BTYVFPD7-1714679925905)]

[外链图片转存中…(img-Kb0kaUhj-1714679925905)]

[外链图片转存中…(img-XuTCreir-1714679925906)]

[外链图片转存中…(img-jJtwPyhq-1714679925906)]

文中展示的资料包括:**《MySql思维导图》《MySql核心笔记》《MySql调优笔记》《MySql面试专题》《MySql性能优化的21个最佳实践》《MySq高级知识笔记》**如下图

[外链图片转存中…(img-OReg04wR-1714679925906)]

关注我,点赞本文给更多有需要的人
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

  • 11
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值