首页 > 编程语言 >Java log框架使用指南

Java log框架使用指南

时间:2022-12-06 11:08:32浏览次数:72  
标签:Java log 实现 jar 接口 slf4j 日志 使用指南 log4j


议题如下:

  • 引言
  • Java世界的log框架发展历程
  • 什么是绑定实现(bingding)
  • 什么是覆盖实现(override)
  • 什么是桥接适配(bridge/route)
  • 日志jar包之间的冲突
  • Spring-boot为我们做了什么?
  • Reference


引言

眼花缭乱的日志jar包,让我们无从下手

Java log框架使用指南_开发语言

Java世界的log框架发展历程

通过时间线整理如下

时间线

日志名称

作者

简介

2001年1月8日

log4j1

Ceki Gülcü/apache

在jdk1.4之前广泛使用(是直接使用实现类,没有接口定义),并成为成为了Apache项目

2002年2月6日

java.util.logging(jul)

sun

sun拒绝把apache的log4j纳入到jdk,并在jdk1.4版本之后新增了jul;没有接口api定义;java.util.logging.Logger;

2002年8月13日

commons-logging(jcl)

apache

鉴于市面上log4j1和jul都广泛使用,但是两者之间的api完全不相同,无法快速切换。则抽象出一套log接口api定义,在运行时可以切换不同的日志实现组件。

目前已经停止更新了。

2006年

slf4j

Ceki Gülcü

虽然Ceki Gülcü认为抽象一套log接口的api定义是好的设计,但是他认为jcl的设计本身并不好用,于是自己开发出slf4j(Simple Logging Facade for Java)——同样也是不提供具体的log实现,只对外提供统一的接口/切面。目的就是要取代jcl

2006年

logback

Ceki Gülcü

Ceki Gülcü同时基于slf4j的抽象,也开发出logback作为log的实现,性能比log4j好。目的就是要取代log4j1

2014年7月

log4j2

apache

apache参考了logback的实现,推出了log4j2;log4j2自身是接口+实现

通过log历史进程,总结如下

Java log框架使用指南_jar_02

  • 两大日志接口:jcl(commons-logging),slf4j
  • 目前一统江湖的就是apache的commons-logging和slf4j,他两的作用就是提供统一的接口,而具体的日志实现交给底层绑定的具体的日志实现框架。这样一来,我们的业务系统中可以灵活的更换不同的日志实现,并且可以不需要去改动代码。
  • 对于开发者而言,每种日志都有不同的写法。如果我们以实现的日志框架来进行编写,代码就限制死了,之后就很难再更换日志系统,很难做到无缝切换。
  • 抽象与实现分离。

什么是绑定实现(bingding)

JCL的绑定情况如下

接口名称

接口的jar

实现名称

实现的jar

实现的jar的含义

commons-logging(jcl)

commons-logging.jar

logging(jul)

jdk自带的日志实现


动态绑定

commons-logging.jar

log4j1(jcl亲儿子)

log4j.jar

log4j 一代版本就一个依赖jar,最高版本是12;log4j一代默认实现了jcl的api

spring

commons-logging.jar

log4j2

log4j-api.jar

定义的api


log4j-core.jar

api的实现


log4j-jcl.jar

把log4j二代绑定到jcl;log4j二代默认实现的api是log4j-api.jar



logback默认不支持

默认不支持

logback是默认是基于slf4j实现

slf4j的绑定情况如下

接口名称

接口的jar

实现名称

实现的jar

实现的jar的含义

slf4j

slf4j-api.jar

logging(jul)

slf4j-jdk14.jar

slf4j绑定到jdk-logging;java.util.logging.Logger

静态绑定

slf4j-api.jar

log4j1

slf4j-log4j12.jar

slf4j绑定到log4j


log4j.jar

log4j 一代版本就一个依赖jar,最高版本是12


slf4j-api.jar

log4j2

log4j-slf4j-impl.jar

slf4j绑定到log4j2二代;

注意,这个是apahce自己去实现的,并不是slf4j提供的


log4j-api.jar

log4j 二代版本的api


log4j-core.jar

log4j 二代版本的实现


slf4j-api.jar

logback(slf4j亲儿子)

logback-core.jar

logback的核心包


logback-classic.jar

logback默认实现了slf4j的API


slf4j-api.jar

jcl

slf4j-jcl.jar

slf4j绑定到jcl

slf4j官网的介绍

Java log框架使用指南_开发语言_03

  • Slf4j厂商并没有开发支持log4j2的绑定代理jar;Apache开发了基于log4j2绑定代理jar:log4j-slf4j-impl
  • 从maven仓库可以看到相关binding的字样

绑定实现的总结

jar包命名规则

abc-xyz.jar:把abc绑定到xyz;abc作为接口存在,把实现绑定到xyz的实现上

使用场景

接口与实现之间的关系,就被当做一种绑定;

存量的项目中已经迁移到slf4j api上面来,但是发现一些场景必须使用其他的日志实现(jcl/log4j);

比如:配置文件不想修改,依赖的jar/项目里面直接使用了实现类,依赖的jar里面有配置文件等等;


————针对这种场景,需要的是一种绑定的概念,英文单词为bingding,把abc绑定到xyz;
然后,再与加入该日志框架的具体实现jar包;

提供商

通常情况下,由该接口的厂商提供;目的在于让自己所出品的接口作为统一接口,但是可以让用户选择业界不同的日志实现框架

结论:接口是slf4j,实现则是其他日志框架(自己出品的接口,可以支持别人去实现)

什么是覆盖实现(override)

使用场景

源日志框架

需要依赖jar

目标日志框架

jcl

jcl-over-slf4j.jar

slf4j

log4j1

log4j-over-slf4j.jar

slf4j

覆盖实现的总结

jar包命名规则

abc-over-xyz:abc的实现被xyz覆盖掉;abc作为实现,可以被xyz的实现所覆盖掉———提供了相同的包.类

使用场景

场景一,老项目的代码和配置是使用标准的api(接口+基础class),那么code+配置文件多是0修改。

场景二,新项目自身采用的是slf4j api日志框架,但是开发过程中依赖的组件(spring)/框架,其内部已经采用了某种日志框架,并且这些组件/框架内容使用了面向接口编程(但不是slf4j接口);
针对实现层的替换(而不是并存),如果项目依赖了over的jar包,则需要排除掉之前的默认实现的jar包;
比如spring就是使用jcl居多,而自己的项目使用的logback相关的log配置,让spring的jcl日志的实现层用slf4j的实现来替代,这样用一套logback的配置就可以打印spring的日志了;

提供商

由slf4j提供,致力于为不同的接口定义,提供slf4j的搞性能实现。

结论:接口不是slf4j,实现则是slf4j(别人的亲儿子,我也要替换。)老接口,新实现,旧实现尽量排除

扩展内容,细节介绍


Override 为了实现覆盖的效果:是通过提供同名的包 . 类的方式 —— 去替换原先的 jar 包里面的包 . 类。


所以理论上 override 的 jar 包,不可以与原先实现的 jar 包并存的,是要排除掉原先的 jar 包的


如果很难排除原先的 jar ,保证 override 的 jar 优先被加载,也是可以的。


•Slf4j的亲儿子logback的具体实现,是一定要依赖的。


如果项目里面直接使用具体的实现子类,那么 override 的 jar 包是失效的


通过 jar 的源码可以提高自身对 override的理解:打开log4j-1.2.17.jar与log4j-over-slf4j-1.7.30.jar你会发现他们包含了同名的包.类





 


什么是桥接适配(bridge/route)

使用场景

源日志框架

需要依赖jar

目标日志框架

实现的jar的含义

jul

jul-to-slf4j

slf4j

把jul的实现桥接到slf4j的实现上

(Jul是jdk自带的,没办法排除jar包,只能做桥接)

log4j2

log4j-to-slf4j

slf4j

把log4j2的实现桥接到slf4j的实现上

(项目里面用了log4j2的api,Slf4j厂商并没有开发支持log4j2的override的jar包。Apache厂商就自己开发。)

强调:选择“桥接适配”的方案,是只有当“ override ”方案不支持的时候,所选择的


不 到万不得已,不要选择该方案的 jar 包 —— 该方案会导致 log 的性能大幅度下降


jar 包命名规则 abc -to-xyz : abc 的实现被转发(桥接 / 路由 / 适配)到 xyz 的 实现


负责桥接的 jar 包与具体实现的 jar 包并存






官方对桥接适配的介绍

​Log4j Bridge​

​https://​​​​logging.apache.org/log4j/2.x/log4j-to-slf4j/index.html​


日志jar包之间的冲突

A

B

冲突原因

logback-classic.jar

log4j-slf4j-impl.jar

两者都是针对slf4j的实现,运行时不能同时存在;

log4j-to-slf4j.jar

log4j-slf4j-impl.jar

spring-boot的log框架校验机制。Spring-boot认为:在maven依赖上,如果依赖了log4j-to-slf4j.jar,则认定将log4j2的实现,交给slf4j了,那么就应该是走slf4j亲儿子去实现(logback);而依赖log4j-slf4j-impl.jar了意味着让log4j2作为slf4j的实现存在;

jcl-over-slf4j.jar

slf4j-jcl

jcl-over-slf4j.jar意味着用slf4j所提供的实现去覆盖jcl的实现;

slf4j-jcl意味着用jcl的实现slf4j接口;

log4j-over-slf4j.jar

slf4j-log4j12

同上

jul-to-slf4j.jar

slf4j-jdk14

同上

Spring-boot为我们做了什么?


spring-boot-starter-log4j2

用途:项目中所有的日志框架,可以转换成——以slf4j为接口,以log4j2为实现。

GroupId

ArtifactId

简介

org.springframework.boot

spring-boot-starter-log4j2

默认不推荐,因此默认不传递依赖,需要项目手动依赖;

用于让项目采用面向slf4j接口api编程,但是采用log4j2实现的场景

spring-boot-starter-logging

用途:项目中所有的日志框架,可以转换成——以slf4j为接口,以logback为实现。


GroupId

ArtifactId

简介

org.springframework.boot

spring-boot-starter-logging

默认推荐,默认传递依赖;如果不想依赖,则需要手动排除


总结


但是 spring-boot 所提供的两个 log 依赖,都不包含 Override 的 jar 。


Override 的 jar 包是用来适配的场景是: 接口不是 slf4j ,但是实现层可以是 logback 。


所以, spring-boot 所提供的两个 log 依赖,仅仅是支撑 slf4j 作为 api 的场景所需要的。



Reference




​SLF4J Manual​



• ​http​​ ​​://www.slf4j.org/legacy.html



​https://​​ ​​logging.apache.org/log4j/2.x/log4j-to-slf4j/index.html​






标签:Java,log,实现,jar,接口,slf4j,日志,使用指南,log4j
From: https://blog.51cto.com/u_15903664/5915133

相关文章