目前java中有很多的日志组件,Log4J,logback和 java.util.Logging 等,不同项目做对接的话可能涉及到不同的日志处理模块,同一个项目里面若是引用了第三方的 jar 库,还可能连带引用对应的日志库,所以比较麻烦。后来查阅了 SLF4J
,比较满意。
Java 日志组件总览
SLF4J(The Simple Logging Facade for Java) 是一个简单日志门面抽象框架,它本身只提供了日志 Facade API 和一个简单的日志类实现,一般常配合 Log4j,LogBack,java.util.logging 使用。 SLF4J
作为应用层的 Log 接入时,程序可以根据实际应用场景动态调整底层的日志实现框架(Log4j/LogBack/JdkLog…);
LogBack和Log4j都是开源日记工具库,LogBack 是 Log4j 的改良版本,比 Log4j 拥有更多的特性,同时也带来很大性能提升。详细数据可参照下面地址:Reasons to prefer logback over log4j
建议在项目里使用日志时都配合 Slf4j 使用,这样可以灵活地替换底层日志框架。
SLF4J 的优势
这是在 Log4j 中使用的方式
if (logger.isDebugEnabled()) {
logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
}
这是换成 SLF4J+Log4J 的方式
logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
好处如下:
- 不需要字符串连接而且不会导致暂时不需要的字符串消耗
- 在生产最终日志信息的字符串之前,这个方法内部会检查一个特定的日志级别是不是打开了,这不仅降低了内存消耗而且预先降低了 CPU 去处理字符串连接命令的时间
所支持的日志系统
NOP, Simple, log4j, JDK logging, JCL and logback
核心jar
slf4j-api.jar
支持其他
SLF4J+Logback
slf4j + Logback 配套使用,所需引用包括: slf4j-api.jar
, logback-core.jar
, log-classic.jar
SLF4J+Log4J
SLF4J+Log4J配套使用,所需引用包括:slf4j-api.jar
, log4j.jar
, slf4j-log4j.jar
SLF4J+simplelog
SLF4J+Log4J配套使用,所需引用包括 slf4j-api.jar
, slj4j-jdk.jar
经典使用方式
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// ...
Logger logger = LoggerFactory.getLogger(YourClazz.class);
logger.info("Temperature has risen above {} degrees.", 50);
// ...
绑定原理
以 commons-logging 为例,引入 org.slf4j.jcl-over-slf4j-1.5.6.jar,这个jar 包提供了一个桥接,让底层实现是基于slf4j 。原理是在该 jar 包里存放了配置
META-INF/services/org.apache.commons.logging.LogFactory =org.apache.commons.logging.impl.SLF4JLogFactory
而 commons-logging 在初始化的时候会找到这个 serviceId ,并把它作为LogFactory 。
简单日志门面 SLF4J 内部又是如何来装载合适的log 呢?
原理是 SLF4J 会在编译时会绑定 import org.slf4j.impl.StaticLoggerBinder;
该类里面实现对具体日志方案的绑定接入。任何一种基于 slf4j 的实现都要有一个这个类。如:
org.slf4j.slf4j-log4j12-1.5.6
: 提供对 log4j 的一种适配实现。
Org.slf4j.slf4j-simple-1.5.6
: 是一种 simple 实现,会将 log 直接打到控制台。
……
注意事项
如果有任意两个实现 slf4j 的包同时出现,那就有可能酿就悲剧,你可能会发现日志不见了、或都打到控制台了。原因是这两个jar 包里都有各自的 org.slf4j.impl.StaticLoggerBinder
,编译时候绑定的是哪个是不确定的。
建议在 maven 中设置 exlude 进行排查。