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

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

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

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

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

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

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

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

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

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

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

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

经过这样三步,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

相关文章
相关标签/搜索