一、什么是日志?
在生活上,日志是一种日记,用于记录我们生活的一点一滴,我们可以通过日志回忆美好,平淡抑或是痛苦的过往。对于我们的程序来说日志就是记录
某个时刻应用执行的信息,错误等。
在没有比较成熟,好用的日志框架出现之前,我们程序员该这么打印日志呢?一千个哈姆莱特有一千个实现,没有统一的标准,每个公司都是闭门造车,
A公司造的车子是两个轮子的,B公司的是四个轮子,C公司不仅能在地上跑还能在天上飞,所以这三家公司的日志框架只能给自家用,无法开源给
其他公司使用,每个公司可能都要根据自己的情况造自己的车。
那么现在比较成熟,集大家之成,通用的框架实现有哪些呢?
我们比较熟悉的有log4j,logback等,log4j和logback的作者都是Ceki Gülcü,也在此基础上抽象出了 slf4j api,全称为 The Simple Logging Facade for Java,用来定义日志门面,logback 是在log4j与slf4j基础上优化而来,所以logback的性能要优于log4j,所以本博文将研究logback的源码实现
二、既然有那么多的日志实现,那如果我同时引入了log4j和logback等多个框架,将会使用哪个呢?
启动项目的时候会打印警告信息,信息如下:
SLF4J: Class path contains multiple SLF4J bindings.
那么这个信息是怎么打出来的呢?
// 获取日志上下文,内部会自动绑定当前存在的日志实现
org.slf4j.ILoggerFactory loggerContext = org.slf4j.LoggerFactory.getILoggerFactory();
上面这个方法会自定绑定日志实现,在绑定之前会判断当前系统中存在的实现是否有多个,如果有多个那么将会提示警告信息,具体代码
如下:
static Set<URL> org.slf4j.LoggerFactory.findPossibleStaticLoggerBinderPathSet() {
// use Set instead of list in order to deal with bug #138
// LinkedHashSet appropriate here because it preserves insertion order
// during iteration
Set<URL> staticLoggerBinderPathSet = new LinkedHashSet<URL>();
try {
ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader();
Enumeration<URL> paths;
if (loggerFactoryClassLoader == null) {
// STATIC_LOGGER_BINDER_PATH =》org/slf4j/impl/StaticLoggerBinder.class
paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
} else {
paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH);
}
while (paths.hasMoreElements()) {
URL path = paths.nextElement();
staticLoggerBinderPathSet.add(path);
}
} catch (IOException ioe) {
Util.report("Error getting resources from path", ioe);
}
return staticLoggerBinderPathSet;
}
上面这段代码会检查类路径下有多少个 org/slf4j/impl/StaticLoggerBinder.class,如果出现多个那么将会警告多个实现的日志,那么问题
来了,既然只是警告没有抛出错误,那么它到底最后使用的是哪个日志实现呢?这个主要看系统加载文件的顺序了,在不同的系统上它的加载
顺序可能不相同,比如我在mac电脑上启动能正常打印日志,但是在linux上却不能,所以最后一个系统里就只留一个日志实现,不要出现多个。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?