正如Spring官方文档所述,其底层的实现选择了commons-logging作为日志框架。这一“失足”性的选择,竟连Spring自身都抱怨。但是,谁叫Spring如此优秀呢,即使有一点小瑕疵,人家也得完美的兼容下去。所以,直到目前的版本,commons-logging仍然是默认的日志框架。

但是,大多数的应用开发(也包括我自己做过的应用),都没有选择commons-logging这个日志框架,而是SLF4j 或者 Log4j 之类的。

那有没有办法,像其它很多开源框架一样,替换掉其默认的commons-logging呢?显然,是有的!

从Spring官方文档中可以看出,它其实也只有 spring-core 这个模块依赖了commons-logging,所以,替换掉它就可以了。

以使用SLF4j框架来替换为例,具体的替换步骤如下(参照官网):

  1. 从 spring-core 的依赖中排除掉 commons-logging 依赖。
  2. 添加 jcl-over-slf4j 依赖。
  3. 添加 slf4j 以及 log4j 依赖。

详细说明如以下截图所示:

第一步:排除对 commons-logging 的依赖。

第二步:添加接管 commons-logging 的依赖。

刚开始的时候,自己也不理解为什么添加这样一个特殊的依赖且不用修改源码就可以让Spring的日志自动转到 slf4j 上来呢?其实,不难理解,这真的是一个“接管”包,因为其内部的Log接口以及最常用的LogFactory类都与原来 commons-logging 中的一样!所以,底层代码就完全不需要改变,同时,输出日志信息的方法调用就自动转到了这个 jcl-over-slf4j 包的方法上。这样就实现了“接管”。

第三步:添加 slf4j 及 log4j 依赖。

通过这样三步,commons-logging 的日志方法调用就全部转嫁到 jcl-over-slf4j,再到 slf4j 最后到 log4j 上面了。

我没有直接使用 Log4J 来接管,因为 slf4j 比 log4j 更好一些(主要体现在占位符以及Debug和Trace日志不用全部拼接字符串的逻辑上)。

现在Spring官方文档的格式好像改版了,没有以前那样可以直接在一个Html页面中显示出来(进而可以保存为PDF并打印)。所以,在此贡献一个我当年从单个Html页面中保存下来的PDF文档吧。同时,上述接管 commons-logging 的原文也可以在第2章中找到。

本PDF是Spring的 4.3.5.RELEASE 版本。

链接地址:https://github.com/cyhbyw/spring-framework/blob/Branch_v4.2.5.RELEASE/Spring%20Framework%20Reference%20Documentation.pdf

============================================================================================================================

上面的接管其实还比较简单,而且也能看到,这是在Spring源码之外且基于Maven来管理的。问题是:如何在Spring源码中替换呢?

Spring源码使用了Gradle来管理,所以,应该能够想到,是通过直接修改 build.gradle 文件来完成的。

我自己在GitHub上Checkout出来后使用的是 4.2.5.RELEASE 版本,可以看到,这个版本的 build.gradle 文件有1400+行。自己没有系统学习和使用过Gradle,于是,依照着对maven的理解,开始改吧。

依旧可以清晰地看到,Spring下的十几个模块在 build.gradle 文件中都有类似于 project("spring-core") 这样的关键字。在这其中还可以看到 dependencies 关键字,不用想,这和Maven中的 dependencies 一样,就是依赖了。

明显,commons-logging 的依赖位列其中。所以,想办法将它替换成 slf4j 应该就可以了。

可是,咋个改呢??

开始的尝试(第一次)是:

  1. 删除 commons-logging 这一行的依赖
  2. 添加 jcl-over-slf4j 依赖、slf4j-api 依赖以及 slf4j-log4j12 依赖(都是 compile 范围)
  3. 将 optional 的 log4j 依赖改为 compile

为什么要这样做呢?很简单,完全是从上面的Maven中照搬过来的!然而,悲剧发生了,改了后它就是不正常。更奇怪的是,它会报 spring-context 对 spring-beans-groovy 的依赖找不到!

完全无解,憋了好久也没想出个办法。。。

完全无解,憋了好久也没想出个办法。。。

完全无解,憋了好久也没想出个办法。。。

没办法,只有尝试了。整个操作的现象就是,添加了上述依赖后,它就报 spring-context 对 spring-beans-groovy 的依赖找不到!于是,我少少地添加呗,再不济,一个一个地添加呗。

现在的尝试(第N次)是:

  1. 删除 commons-logging 这一行的依赖——因为要排除掉 commons-logging 的依赖,所以这一步是必须的!
  2. 添加 jcl-over-slf4j 依赖、slf4j-api 依赖以及 slf4j-log4j12 依赖(都是 compile 范围)——因为排除 commons-logging 后,源码中直接报错,没有需要的类,所以,这些依赖必须加进来。

只操作了上述两步,再一试,还是报错,但错误不一样了,而且一看就懂,大概就是说找不到类,而且是 log4j 中的 Log 类(其实是接口),而且错误是在 spring-context 是报出来的,于是,尝试再在 spring-context 的依赖中添加 log4j 的依赖。结果,成了!

对Gradle不熟悉,所以,虽然问题是解决了也可以正常运行了,但是,RootCause还是不清楚。而且从上述截图中也可以看到 spring-core 的依赖中已经有 optional 的 log4j 依赖了,而我之前是直接把这个 optional 改成 compile 了,会不会有影响?而最后能正常运行的时候,这个 optional 的 log4j 仍然是存在的,只是在 spring-context 中添加了 compile 的 log4j。

献上自己从GitHub Fork并“践踏”过的Spring源码地址:https://github.com/cyhbyw/spring-framework/tree/Branch_v4.2.5.RELEASE

Spring源码学习:第2步--使用SLF4j+Log4j日志框架替换掉其自身的commons-logging日志框架的更多相关文章

  1. spring源码学习之路---深入AOP(终)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章和各位一起看了一下sp ...

  2. spring源码学习之路---IOC初探(二)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章当中我没有提及具体的搭 ...

  3. Spring源码学习-容器BeanFactory(四) BeanDefinition的创建-自定义标签的解析.md

    写在前面 上文Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签对Spring默认标签的解析做了详解,在xml元素的解析中,Spri ...

  4. Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签

    写在前面 上文Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作中Spring对XML解析后创建了对应的Docum ...

  5. Spring源码学习-容器BeanFactory(一) BeanDefinition的创建-解析资源文件

    写在前面 从大四实习至今已一年有余,作为一个程序员,一直没有用心去记录自己工作中遇到的问题,甚是惭愧,打算从今日起开始养成写博客的习惯.作为一名java开发人员,Spring是永远绕不过的话题,它的设 ...

  6. Spring源码学习笔记9——构造器注入及其循环依赖

    Spring源码学习笔记9--构造器注入及其循环依赖 一丶前言 前面我们分析了spring基于字段的和基于set方法注入的原理,但是没有分析第二常用的注入方式(构造器注入)(第一常用字段注入),并且在 ...

  7. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  8. Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点

    Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...

  9. Spring源码学习

    Spring源码学习--ClassPathXmlApplicationContext(一) spring源码学习--FileSystemXmlApplicationContext(二) spring源 ...

  10. Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作

    写在前面 上文 Spring源码学习-容器BeanFactory(一) BeanDefinition的创建-解析资源文件主要讲Spring容器创建时通过XmlBeanDefinitionReader读 ...

随机推荐

  1. html5版 音乐播放器

    html5版本音乐播放器,支持iOS设备,案例地址:http://www.xttblog.com/?p=1277 功能说明 支持iOS设备,但是iOS不支持自动下一曲,这是iOS本身限制,支持touc ...

  2. 阿里巴巴十年Java架构师分享,会了这个知识点的人都去BAT了

    1.源码分析专题 详细介绍源码中所用到的经典设计思想,看看大牛是如何写代码的,提升技术审美.提高核心竞争力. 帮助大家寻找分析源码的切入点,在思想上来一次巨大的升华.知其然,并知其所以然.把知识变成自 ...

  3. Codeforces446C - DZY Loves Fibonacci Numbers

    Portal Description 给出一个\(n(n\leq3\times10^5)\)个数的序列,进行\(m(m\leq3\times10^5)\)次操作,操作有两种: 给区间\([L,R]\) ...

  4. java.net.UnknownHostException

    java.net.UnknownHostException 错误解决方向 查看 测试真机或者模拟机是否连上了网络.     如果不是第一步错误的话,一般就是测试机没有链接上网络,可以打开个网页或者其他 ...

  5. 【视频教程】一步步将AppBox升级到Pro版

    本系列教程分为上中下三部分,通过视频的形式讲解如何将基于FineUI(开源版)的AppBox v6.0一步一步升级FineUIPro(基础版). [视频教程]一步步将AppBox升级到Pro版(上)主 ...

  6. 从零开始学习前端JAVASCRIPT — 14、闭包与继承

    一.闭包 1 . 概念:闭包就是能够读取其他函数内部变量的函数.在JS中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解为”定义在一个函数内部的函数”. 2 . 闭包的特点 1)可以读取 ...

  7. SDP(9):MongoDB-Scala - data access and modeling

    MongoDB是一种文件型数据库,对数据格式没有硬性要求,所以可以实现灵活多变的数据存储和读取.MongoDB又是一种分布式数据库,与传统关系数据库不同的是,分布式数据库不支持table-join,所 ...

  8. shell脚本 字串截取 正则表达式

    字串处理 子串截取方法一:使用${}表达式格式:echo ${x:起始位置:长度}(起始位置编号从0开始,可省略) 方法二:使用expr substr格式:expr substr "$x&q ...

  9. grub2与grub区别

    关于版本: GRUB2 使之版本号为1.98之后的grub:GRUB legacy(版本为0.97)是指GRUB,而非GRUB2,grub是指 grub1.97 和以前的,grub 2 指的是 gru ...

  10. Java中的换行符

    Java中的换行符 PrintWriter out = response.getWriter(); out.write("\r\n"); Java中的换行符"\r\n&q ...