1.常用的搭配
当项目中没有日志框架的时候,可以直接引用下面的 jar 包,来实现日志模块的使用:
总结一下就是:
- logback : slf4j-api.jar + 无桥接 + logback-classic.jar + logback-core.jar
- log4j : slf4j-api.jar + 桥接[slf4j-log4j12.jar] + log4j.jar
- log4j2 : slf4j-api.jar + 桥接[log4j-slf4j-impl.jar] + log4j-api.jar + log4j-core.jar
- jul : slf4j-api.jar + 无桥接 + slf4j-jdk14.jar
- slf4j 无日志实现 : slf4j-api.jar + slf4j-nop.jar
2. 桥接方式
slf4j 支持各种适配,无论你现在是用哪种日志组件,你都可以通过 slf4j 的适配器来使用上 slf4j。只要切换到 slf4j ,就可以再次转换成想要使用的日志框架。总结起来就是下图:
官方图说的比较啰嗦,其实就是上图的另一种表述方式:
3. 原理
slf4j 从 LoggerFactory.getLogger() 开始,经历如下过程:
原理就是就是让 ClassLoader 从 classpath (依赖的 jar) 中找到「StaticLoggerBinder」这个类,然后利用他来返回 log4j、logback 中的 Logger,然后打印日志。
所谓的桥接包,就是实现「StaticLoggerBinder」类,用来连接 slf4j 和日志框架。因为 log4j 和log4j2 刚开始没有该类,为了不改变程序结构,只能重新写一个新的 jar 来实现它。而 logback 出现slf4j 之后,于是在其本身中就实现了该类,所以就不需要桥接包。
因此,遇到如下问题,就可知具体原因:
- “Class path contains multiple SLF4J bindings”
来自上图 “reportMultiBindingAmbiguity()” 的原因,多个实现了 「StaticLoggerBinder」类冲突,slf4j 无法确定到底用哪个日志框架。因此 logback-classic、log4j-slf4j-impl、slf4j-log412、slf4j-jdk 这些 jar 不能同时存在。 - “Failed to load class org.slf4j.impl.StaticLoggerBinder”
没找到日志实现,如果已经有了对应的日志实现依赖,一般来说极有可能是版本不兼容。