当前位置: 首页 > 科技观察

10分钟让你彻底看懂Java中乱七八糟的日志系统

时间:2023-03-15 18:30:19 科技观察

日志框架分为三个部分,包括日志门面、日志适配器、日志库。使用门面设计模式,即Facade进行解耦,让日志的使用变得更加简单,如下图:日志门面门面设计模式是面向对象设计模式之一,日志框架采用这种模式,类似于JDBC的设计理念。仅提供一套接口规范,不负责日志功能的实现。目的是防止用户关注哪个日志库负责日志打印和具体使用字节。目前使用最广泛的日志门面是slf4j和commons-logging。日志库具体实现了日志相关的功能。主流的日志库有3个:log4j、log-jdk、logback。在最早的java中,如果要记录,只能通过System.out或者System.err来完成,非常不方便。log4j就是为解决这个问题而提出的,它是最早诞生的日志库。随后JDK在1.4版本也引入了一个日志库java.util.logging.Logger,简称log-jdk。这样,市面上有两种日志功能实现,开发者在使用时需要注意所使用的日志库的具体字节数。Logback是最新出现的。它来自与log4j相同的作者。它是log4j的升级版,本身实现了slf4j的接口。日志适配器日志适配器分为两种场景:(1)日志门面适配器,因为后来提出了slf4j规范,而之前的日志库并没有实现slf4j接口,比如log4j,所以如果要使用slf4j在project+log4j模式下,需要额外的adapter(slf4j+log4j2)来解决接口不兼容的问题。(2)日志适配器,在一些老项目中,一开始为了开发简单,直接使用日志库API完成日志打印。随着时间的推移,我想把原来直接调用日志库的模型改成行业标准的门面模型(比如slf4j+logback组合),但是老项目代码中打印日志的地方太多了,而且很难改变,所以需要一个适配器来完成从旧日志库的API到slf4j的路由,这样原来的代码不改变也可以使用slf4j统一管理日志,它是将来自由更换特定日志库不是问题。1.ApacheCommonsLogging(JCL)Commons本身只提供日志接口,具体实现是在运行时动态查找对应的组件?其思想类似于JDBC的抽象。JCL动态搜索(绑定)日志组件的原理是这样的:JCL为每一种类型的日志使用一个适配器,使用哪一个是按照指定的顺序在类路径中动态搜索对应日志的实现。如果JCL在运行时没有找到第三方日志实现,使用jdk14自带的java.util.logging(JUL)。Springlog使用JCL,解决了应用和框架日志不一致的问题,动态搜索(应用配置)日志系统的实现。默认的LogFactory遵循以下步骤来发现和确定将使用哪个日志工具。LogFactory按顺序查找,找到第一个工具后停止。首先在classpath下寻找自己的配置文件commons-logging.properties,如果找到了,就使用其中定义的Log实现类;如果找不到commons-logging.properties文件,检查系统环境变量org.apache是??否定义了.commons.logging.Log,如果找到,则使用其定义的Log实现类;否则,检查类路径下是否有Log4j包,如果有则自动使用Log4j作为日志实现类;否则,使用JDK自带的日志实现类(JDK1.4以后才有日志实现类);否则,使用commons-logging提供的简单日志实现类SimpleLog;提供接口或者门面,所以不是具体的日志解决方案,而是通过FacadePattern对外提供了一些java日志API。对外提供的核心API是一些接口和LoggerFactory工程类。与Commonlogging不同的是,它是用来寻找ClassPath下的jar包来表示具体实现的slf4j-log4j12.jar(表示指定logh4j)slf-jdk14.jar(表示使用JUL)slf4j-jcl。jar(表示使用JCL)log4j-slf4j-impl.jar(表示指定log4j2)logback-classic(logback)SLF4j静态绑定日志组件原理:3.常用日志组件4.适用场景4.1slf4j使用log4j打印日志slf4j-api.jarslf4j-log4j12.jarlog4j.jarJCL方式常见的日志记录是动态搜索绑定SLF4j是静态绑定,需要添加bridge包,比如SLF4j-log4j2可以通过如下配置集成<依赖>org.slf4jslf4j-api${slf4j-api.version}org.slf4jslf4j-log4j12${slf4j-log4j12.jar.version}log4jlog4j${log4j.version}如果老代码直接使用log4j日志库提供的接口打印日志,你还需要引入日志库适配器,配置示例如下:}}}}/version>4.2slf4j使用logback打印日志如果是新项目,建议使用slf4j+logback模式,因为logback本身实现了slf4j的接口,不需要引入额外的适配器,在另外,logback是log4j的升级版,具有比log4j更多的优势,可以通过如下配置集成:org.slf4jslf4j-api${slf4j.version}ch.qos.logbacklogback核心${logback.version}版本>ch.qos.logbacklogback-classic${logback.version}4.3spring集成log4j2我们的应用使用log4j2打印日志;Spring使用的JCL不包含log4j2,运行时JCL从ClassPath中寻找日志如果不参考其他实现,最终会使用JUL实现下图:这时候会出现什么问题?Spring打印日志和应用打印日志不统一,错误排查困难。而且,应用和Spring框架,日志不统一,太乱了。为了让Spring和我们的应用采用统一的log4j2日志系统,需要添加一个适配器来提高上述应用和框架日志的统一性(添加适配器后),如下图:org.slf4jslf4j-api1.7.25org.apache.logging.log4jlog4j-slf4j-impl2.3org.slf4jjcl-over-slf4j1.7.13org.apache.logging.log4jlog4j-core2.3org.apache.logging.log4jlog4j-api2.3com.lmaxdisruptor3.3.4SLF4j如何集成其他日志框架:5.良好实践使用SLF4J时需要注意以下几点:privatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(XXX.class);logger定义为静态变量是因为这个LOGGER绑定了当前类Set,避免每次new一个新对象,造成资源浪费