还在用log.isDebugEnabled()判断debug日志?你out了

您所在的位置:网站首页 ut_debug 还在用log.isDebugEnabled()判断debug日志?你out了

还在用log.isDebugEnabled()判断debug日志?你out了

#还在用log.isDebugEnabled()判断debug日志?你out了| 来源: 网络整理| 查看: 265

  作为程序员,程序开发写代码一定少不了记录日志(没日志的代码都是耍流氓!)今天记录一下自己新搭建spring-boot项目后对日志的思考。

  起因:项目是一个无页面,通过直接访问数据库,然后调用第三方api实现数据上传的简单应用。因为项目很小,所以在项目完成后,为了使jar包的大小更小(强迫症,想把无用的maven引用全部去掉),所以打包完成后对lib下的jar包进行查看,发现关于log的jar包很多,由此引发联想,难道一个简单的日志都要用这么多的jar包吗?

logjar包.png 查看自己的代码,发现只用到了如下代码

日志引用.png 先说结论

commons-logging和slf4j是java中的日志门面,即它们提供了一套通用的接口,具体的实现可以由开发者自由选择。log4j和logback则是具体的日志实现方案。这是典型的门面模式

比较常用的搭配是commons-logging+log4j,slf4j+logback

spring默认使用commons-logging+log4j

spring-boot默认使用slf4j+logback

SLF4J是编译时绑定到具体的日志框架,性能优于采用运行时搜寻的方式的commons-logging

不需要使用logger.isDebugEnabled()来解决日志因为字符拼接产生的性能问题

logger.info("my name is {}", "medusar"); logger.info("my name is " + "medusar"); 复制代码

在效率上,第一行比第二行更高,因为如果当前日志级别是ERROR,第一行不会进行字符串拼接,而第二行,无论日志级别是什么,都会先进行字符串拼接。

所以为了解决这个问题,commons-logging等框架提供了下面的方式:

if (log.isDebugEnabled()){ log.debug("dddd"+"eee"); } 复制代码

所以说,现在使用spring-boot开发,已经不需要再使用log.isDebugEnabled()来判断debug了

下面我们顺藤摸瓜开始今天的寻根之旅!

先看下slf4j的实现

slf4j接口实现.png 配合第一张图,可知:

可单独只使用slf4j 复制代码 logback就是默认slf4j的实现(logback-classic.jar,logback-core.jar) 复制代码 log4j的slf4j实现要通过log4j-to-slf4j.jar 复制代码 将java.util.logging的日志桥接到slf4j实现要通过jul-to-slf4j-1.7.36.jar 复制代码

这些包的目的是什么?

答案是:统一日志记录。a(slf4j+logback): Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis、xxxx等等,每个框架都是自己使用的日志框架,如何统一他们的?

将系统中其他日志框架先排除出去; 用中间包来替换原有的日志框架; 我们导入slf4j其他的实现

说白了就是,其他的框架还以为他们用的还是自己的日志框架,而实际上,他们的日志框架已经不存在了,存在的是slf4j替换过后的对原有框架的实现的中间包

形象的比喻是:春秋战国时期,各个诸侯纷纷自立为王,他们的臣子都拥戴自己的大王,忽然有一天,秦国的影密卫,将其中几个大王偷偷换成了自己的亲信,让他们代替这几个诸侯国的大王,然后将真正的大王们都杀了,做的神不知鬼不觉,他们的大臣们依然死心塌地的拥戴着自己的大王,并不知道大王已经是替身;实际上他们的大王已经都听命于秦国。表面是各国纷乱,而实际上他们已经实现了统一,都归秦国管理!!!

每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架自己本身的配置文件;

使用logback 配置文件是:

logback.xml:直接就被日志框架识别了。

logback-spring.xml:日志框架就不直接加载日志的配置项,由 SpringBoot 解析日志配置,可以使用 SpringBoot 的高级 Profile 功能。

logback-spring.xml完整配置文件:

logback ${log_pattern} ${log_path}/app.log ${log_pattern} UTF-8 ${logpath}/info/app${log_fileNamePattern} ${log_maxFileSize} ${log_maxHistory} DEBUG ${log_path}/sql.log ${log_pattern} ${log_path}/sql-${log_fileNamePattern} ${log_maxFileSize} ${log_maxHistory} 复制代码

使用log42 配置文件是(pom排除其他,引入中间包):

log4j2.xml

log4j2-spring.xml

使用jul 配置文件是(pom排除其他,引入中间包,存在已知的类加载问题,这些问题会导致从“可执行 jar”运行时出现问题。建议在从“可执行 jar”运行时尽可能避免使用。):

logging.properties

  补充,以前我们使用spring的时候,Logging是spring中唯一强制的外部依赖,spring中默认使用的日志是commons-logging,简称JCL,这里说的强制性,是因为在spring-core这个模块中引入了该依赖。不过,引入了该依赖,也无需做任何其他的配置,它是日志门面,它内部会有自己的算法去找日志门面的实现类,比如log4j,如果说没有引入其他日志依赖,它默认就会去找JDK自带的java.util.logging简称jul作为其日志实现类

log4j1.x版本已经停止更新了,log4j2.x习惯性叫做`log4j2`。(大家还记得前段时间关于log4j漏洞的事情吧) 复制代码

更换spring的common-logging日志系统 依赖配置,排除commons-logging

org.springframework spring-orm commons-logging commons-logging 复制代码

这个时候如果运行程序会抛异常,因为我们把 Spring 依赖的 commons-logging 排除了, 而这个依赖是必须有的,不是可选的。

加入转换包

这个转换包就相当于我们上面说的那个转换器,spring会调用jcl-over-slf4j,spring以为调用的还是commons-logging,但是实际上commons-logging已经被我们删除掉了,并且jcl-over-slf4j还可以将输出转换为slf4j类型的输出,又因为我们前面引入了logback的依赖,lagback是slf4j的实现,所以最终输出的就是logback的日志系统

org.slf4j jcl-over-slf4j 复制代码


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3