日志在工作中起到关键作用,我们经常使用它来打印关键信息,方便分析,或者是输出错误信息,用于bug排查,spring中同样使用了日志进行信息的输出,但是spring4和spring5之间的日志又有些不同,接下来我们就进行一些分析。

1. 各种日志技术简述:  

    log4j,jul,jcl,log4j2,slf4j

    我们先把他们展示出来,以免引用错误。

  1.1 log4j

   使用log4j需要引入log4j的配置文件log4j.properties,内容简配一下:

log4j.rootLogger = info,stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

  pom文件中只引入log4j所需要的jar包

  

  程序也写的简单一点,输出日志就行:

  

  结果:

  

  日志是输出的。

 1.2JUL

  JUL 是jdk自带的,所以pom文件中不需要引入任何包,直接撸代码:

  

  结果:

  

  日志输出格式我们不再做改变,记住log4j和jul的日志输出格式,后面有用到。

 1.3:JCL

  pom中引入所需要的包:

  撸代码:

  

  结果:

  

  呜呼,这个日志输出是不是很眼熟呀,长得很像上面JUL打印出来的日志,难道他们之间有什么不可描述的事情?所以最帅的我准备打开JCL的源码一探究竟。

  从上面代码中的LogFactory的getLog方法下手,进去:

  

  木得意思,就一行代码,那就再深一点,进入getInstance()中,

  

  第一行代码看着像是拿到了log,不过老哥我已经帮大家踩过坑了,debug走了一遍,第一行代码执行后,Log 依然是null,所以我们继续往下走,进入到

this.newInstance()方法中,有点长,就酱紫:

protected Log newInstance(String name) throws LogConfigurationException {
Log instance = null; try {
Object[] params;
if (this.logConstructor == null) {
instance = this.discoverLogImplementation(name);
} else {
params = new Object[]{name};
instance = (Log)this.logConstructor.newInstance(params);
} if (this.logMethod != null) {
params = new Object[]{this};
this.logMethod.invoke(instance, params);
} return instance;
} catch (LogConfigurationException var5) {
throw var5;
} catch (InvocationTargetException var6) {
Throwable c = var6.getTargetException();
if (c != null) {
throw new LogConfigurationException(c);
} else {
throw new LogConfigurationException(var6);
}
} catch (Throwable var7) {
throw new LogConfigurationException(var7);
}
}

  这段代码差一点就比我的长处还长呢,所以我又帮大家debug了一遍,在第一个if判断 之后执行的这个方法 this.discoverLogImplementation(name);就是我们要找的,再深入,在

discoverLogImplementation()这个方法中,我找到了这段代码:

  

  result属性就是我们需要返回的Log,循环条件中有一个classesToDiscover,并且还把他的值传给了this.createLogFromClass()方法,点击看看他是什么,

String[] classesToDiscover = new String[]{"org.apache.commons.logging.impl.Log4JLogger", 
                          "org.apache.commons.logging.impl.Jdk14Logger",
                          "org.apache.commons.logging.impl.Jdk13LumberjackLogger",
                          "org.apache.commons.logging.impl.SimpleLog"};

  这个数组里面找到了 org.apache.commons.logging.impl.Jdk14Logger,这不就是我们的JUL 吗?再想到刚刚的for循环,我们很容易理解,JCL就是循环这个数组,一次获取Log,知道Log 不为null为止,为了验证我们的猜想,

我们可以引入log4j的jar包和配置文件,其他代码不做修改,这样按照数组顺序,应该打印出来log4j的日志。

果然,在有log4j的情况下,JCL按照刚刚那个数组,顺序加载log,知道Log不为null。

  由此可以看出,JCL起到的是一个中间商赚差价的作用,在有log4j的时候使用log4j,否则使用JUL

2 Sring4 的日志体系

  上面说了那么多,只是介绍了一部分日志技术,接下来我们开始分别分析spring4和spring5的日志体系。

 2.1 构建spring4项目

  采用java+注解的方式快速构建,pom中只引入spring-context包

  

  运行下面的代码,可以看到有日志输出

  

  

  找到打印日志的地方,debug模式下,查看输出日志的Log是什么log

  

  可以看出是jdk14Logger,这个在JCL中说过,这个指的是JUL,也就是说在默认spring日志体系下,采用的是JUL,

  接下来,我们按照之前的方法引入log4j,debug运行上面的程序,再次查看日志类型

  

  额,这次在增加log4j jar包和配置文件的情况下,spring4有使用了log4j,这么像JCL呢,木错,让我们在idea中打开spring4的日志依赖结构:

  

  common-logging 这不就是JCL使用到的包吗,可以看出,Spring4使用的是原生的JCL,所以在有log4j的时候使用log4j打印日志,没有的时候使用JUL打印日志。

3.Spring5日志体系

  线上依赖结构图:

  

  答题结构没变,只是原来common-logging ,换成了spring-jcl,看名字就知道是spring自造的包,jcl,更是标注了,它使用的是JCL日志体系。

  所以还是看源码吧。

  按照之前的经验,我们只用debug找到spring内部一个Log,看看他的产生方式和类型。这次我给大家找了AbstractApplicationContext里面找到产生Log的地方

  

  进入这个方法的getLog()中,一直深入,不要怜惜spring,找到LogAdapter中的createLog()方法

  

  可以看出来spring5中对日志的生产,不在像原生JCL中那样使用一个数组,然后进行循环产生,这里用到的是Switch case,这个关键字段LogApi又是在哪一部分赋值的呢?看图

  

  Duang ,没错是在静态代码块中赋的值,为了验证,我们准备用其中提到的log4j2验证(注意:log4j不行,因为这里的switch没有log4j选项),首先我们准备log4j2的配置文件

  

<Configuration status="WARN">

<Appenders>

<Console name="Console" target="SYSTEM_OUT">

<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>

</Console>

</Appenders>

<Loggers>

<Root level="debug">

<AppenderRef ref="Console"/>

</Root>

</Loggers>

</Configuration>

  然后准备pom

  

   代码还是这一行,直接运行:

  结果有日志打印出来了

  

  所以,在spring5中,依然使用的是JCL,但是不是原生的,是经过改造的JCL,默认使用的是JUL,而原生JCL中默认使用的是log4j.

  好了,就酱紫,求轻拍,大家中秋快乐。

  

  

  

  

      

      

      

分析spring4和spring5日志中的不同的更多相关文章

  1. How To:分析ORACLE监听日志中的IP信息

    有时候需要分析出ORACLE日志监听中的IP信息,分享一个组合命令,Linux的shell下运行正常. grep "HOST=.*establish.*\* 0" listener ...

  2. 在linux中使用shell来分析统计日志中的信息

    在运维工作中,要经常分析后台系统的日志,通过抓取日志中的关键字信息,对抓取结果进行统计,从而为监控结果提供基础数据.下面的shell演示了如何从大量的日志中取得想要的统计结果.其中展示了各种有趣的命令 ...

  3. Mysql(Mariadb)慢查询日志中long_query_time 与log_queries_not_using_indexes与min_examined_row_limit 关系分析

    慢查询日志中long_query_time 与log_queries_not_using_indexes与min_examined_row_limit 关系分析   参数介绍: long_query_ ...

  4. Log4j 输出的日志中时间比系统时间少了8小时的解决方法,log4j日志文件重复输出

    1. 第一个问题:时间少了8小时 Log4j 输出的日志中,时间比系统时间少了8小时,但是 eclipse 控制台输出的日志的时间却是对的. log4j配置如下: #all logger output ...

  5. DBA_Oracle LogMiner分析重做和归档日志(案例)

    2014-08-19 Created By BaoXinjian

  6. mysqlsla 分析mysql慢查询日志

    发现有一个工具mysqlsla,分析查询日志比 mysqldumpslow分析的会更清晰明了! 安装mysqlsla: 下载mysqlsla-2.03.tar.gz [root@yoon export ...

  7. 关注LoadRunner脚本回放日志中的Warning信息-转载

    关注LoadRunner脚本回放日志中的Warning信息   最近在与大家的讨论中发现了LoadRunner的很多问题,出于解决问题的出发点,我也就相关自己不理解的问题在Google中搜索了一番,并 ...

  8. fluentd结合kibana、elasticsearch实时搜索分析hadoop集群日志<转>

    转自 http://blog.csdn.net/jiedushi/article/details/12003171 Fluentd是一个开源收集事件和日志系统,它目前提供150+扩展插件让你存储大数据 ...

  9. Nginx日志中的金矿 -- 好文收藏

    转:http://www.infoq.com/cn/articles/nignx-log-goldmine Nginx(读作Engine-X)是现在最流行的负载均衡和反向代理服务器之一.如果你是一名中 ...

随机推荐

  1. scrapy框架与python爬虫

  2. .net core使用MQTT

    废话不多说,我们来直接实践…… 一.搭建mqtt控制台服务端 新建一个.net core控制台项目,然后使用Nuget添加MQTTnet包,我这里使用2.4版本,注意不同版本,代码写法不相同,如下图 ...

  3. 神经网络优化算法:Dropout、梯度消失/爆炸、Adam优化算法,一篇就够了!

    1. 训练误差和泛化误差 机器学习模型在训练数据集和测试数据集上的表现.如果你改变过实验中的模型结构或者超参数,你也许发现了:当模型在训练数据集上更准确时,它在测试数据集上却不⼀定更准确.这是为什么呢 ...

  4. Windows Server 2008配置系统安全策略

    下面学习Windows Server 2008配置系统安全策略 在工作组中的计算机本地安全策略有 用户策略,密码策略,密码过期默认42天 服务账户设置成永不过期,帐户锁定策略,本地策略,审核策略,计算 ...

  5. app登录接口请求报:“签名验证失败”???已解决

    根据抓包数据获得url.param.header,在charles中compose请求结果为成功,在pycharm中运行则报:“签名验证失败”. 运行结果:

  6. Gradle——创建简单的项目

    项目 & 任务 Gradle 的一切都是基于项目和任务的. 构建由一个或多个项目组成.项目的概念很抽象,它取决于你要用Gradle 做什么 .项目可以是 一个 Jar 库或者一个 web 程序 ...

  7. MySQL MGR集群单主模式的自动搭建和自动化故障修复

    随着MySQL MGR的版本的升级以及技术成熟,在把MHA拉下神坛之后, MGR越来越成为MySQL高可用的首选方案.MGR的搭建并不算很复杂,但是有一系列手工操作步骤,为了简便MGR的搭建和故障诊断 ...

  8. js中更改this指向 以及回顾bind、call和apply

    1.更改this指向 方法1:对this进行保存            var _this = this; 例: var _this = this;     document.onclick = fu ...

  9. cocos creator 事件

    cocos creator 事件 在做一个消除类游戏时,需要对点击的方块做出响应.代码很简单,可背后的原理还多着呢. 1. 普通节点注册click事件 在cc中如果需要相应click事件,需要为该节点 ...

  10. Docker学习总结(二)--Docker安装与启动

    注:笔者使用的环境为 CentOS 7.6,如果版本不一致可能会出现一些错误. 安装 Docker 1)将 yum 包更新到最新版本 sudo yum update 2) 安装需要的软件包 sudo ...