Slf4j 包老冲突,每次排查半天,是什么起因?怎样处理?
一、前言
在进行 Java 开发时,通常我们会选择 Slf4j 作为日志门面,但日志实现却不尽相同。假如系统运行中同时存在多个日志实现,就会出现相似下图的 Warning。

二、问题起因
我们知道 SpringBoot 默认使用的日志实现是 Logback,因而我们尝试在项目中引入 Log4j 的依赖时,就复现了上图的报错。

上图报错告知我们存在多个 SLF4J bingdings,分别位于 logback 和 log4j 包中,有两个 StaticLoggerBinder。
我们知道使用 Slf4j ,需要 LoggerFactory.getLogger() 方法获取实例。

我们即可以通过这个作为入口,去看看源码的实现。如下图所示,我标注了需要关注的核心代码。
(1)调用 getILoggerFactory() 方法得到 LoggerFactory。
(2)对于初次调用,INITIALIZATION_STATE 应该是 UNINITIALIZED,所以进入初始化的逻辑,调用方法 performInitialization()。
(3)调用 bind() 方法。
(4)假如不是 isAndroid(),调用 findPossibleStaticLoggerBinderPathSet() 方法,故名思意,查找可能的 staticLoggerBinder,注意这里返回的类型是 SET,就可能是多个。
(5)在findPossibleStaticLoggerBinderPathSet() 这个方法内,首先通过 classLoader 加载了 org/slf4j/impl/StaticLoggerBinder.class 这个类的 path,它可能存在多个,因而使用了 while 获取了所有的 path,并最终返回。

(6)reportActualBinding() 方法会校验 SET 的 size,假如大于 1,就会打印出一开始我们看见的 Warning 了。

三、问题处理
处理思路就是将你不想要的日志实现从依赖包中排除掉就可,通过 IDEA 提供的 Diagrams 能够非常方便的查看项目中的依赖关系。
打开项目的 POM 文件,右键选择 Diagrams -> Show Dependencies

假设我们想要排除 logback 依赖,使用 log4j。Ctrl + F 搜索 logback,可以找到引用该依赖的树形结构。

点击窗口左上角的下图中的这个图标,可以只看当前选中的这个依赖的关系。

选中后效果如下:

如上图所示,logback 由 spring-boot-starter-logging 引入,最顶层是由 spring-boot-starter-web 和 spring-boot-starter-test 引入。
我们尝试在 spring-boot-starter-web 中排除该依赖,应该即可以了。假如排出后重新搜索依然存在 logback 依赖,则重复执行排除的操作。

四、总结
日志框架冲突特别对于新手来说解决起来比较头疼,由于涉及到了日志接口和日志实现。
我们推崇的应该是面向接口编程,因而我们大到开源项目,小到公司的公共 jar 包,应当正当利用 Maven 的传递机制。具体的日志实现不应该传递出去,避免影响到调用的下游方。
<optional>true</optional>
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Slf4j 包老冲突,每次排查半天,是什么起因?怎样处理?