文章目录
- 官网
- SLF4J 简单使用案例分析
- SLF4J 获取 `Logger` 的原理
- 获取 `ILoggerFactory` 的过程
- 获取 `Logger` 的过程
- SLF4J 与底层日志框架的集成
- 小结
官网
https://slf4j.org/
Simple Logging Facade for Java (SLF4J) 用作各种日志记录框架(e.g. java.util.logging、logback、log4j)的简单外观或抽象,允许最终用户在部署时插入所需的日志记录框架 时间。
请注意,启用 SLF4J 的库意味着仅添加一个强制依赖项,即 slf4j-api.jar。 如果在类路径上找不到绑定/提供程序,则 SLF4J 将 default 为 no-operation 实现。
SLF4J user manual:https://slf4j.org/manual.html
SLF4J 简单使用案例分析
在这个简单的使用案例中,SLF4J 的 LoggerFactory.getLogger()
被用来获取一个 Logger
实例,用于记录不同级别的日志信息。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static Logger logger = LoggerFactory.getLogger(Log4jSlf4JTest.class);
public static void main(String[] args) {
if (logger.isDebugEnabled()) {
logger.debug("slf4j-log4j debug message");
}
if (logger.isInfoEnabled()) {
logger.info("slf4j-log4j info message");
}
if (logger.isTraceEnabled()) {
logger.trace("slf4j-log4j trace message");
}
}
LoggerFactory.getLogger()
是获取日志记录器的入口方法,它返回一个实现了Logger
接口的对象。- 日志级别通过
isDebugEnabled()
,isInfoEnabled()
, 和isTraceEnabled()
方法进行判断。
SLF4J 获取 Logger
的原理
LoggerFactory.getLogger()
方法的核心实现如下:
/**
* 获取指定名称的日志记录器
*
* @param name 日志记录器的名称,通常与类名或模块名相对应
* @return 返回一个具有指定名称的Logger对象
*
* 此方法通过委托给全局的ILoggerFactory实例来获取Logger对象
* 使用工厂模式允许日志实现的灵活配置和扩展
*/
public static Logger getLogger(String name) {
// 获取ILoggerFactory实例,该实例负责创建和管理Logger对象
ILoggerFactory iLoggerFactory = getILoggerFactory();
// 调用工厂的getLogger方法,根据名称获取对应的Logger对象
return iLoggerFactory.getLogger(name);
}
获取 ILoggerFactory
的过程
/**
* 获取ILoggerFactory实例
* 该方法通过调用getProvider()方法获取一个日志工厂提供者,并从该提供者中获取一个ILoggerFactory实例
* 主要用于日志功能的配置和管理
*
* @return ILoggerFactory 实例,用于创建和管理日志记录器
*/
public static ILoggerFactory getILoggerFactory() {
return getProvider().getLoggerFactory();
}
获取 ILoggerFactory
实例的过程较为复杂,它涉及到以下几个步骤:
-
查找
StaticLoggerBinder
类
SLF4J
需要通过ClassLoader
查找org/slf4j/impl/StaticLoggerBinder.class
类。StaticLoggerBinder
是 SLF4J 与底层日志框架(如logback
或log4j
)绑定的核心类。ClassLoader.getSystemResources("org/slf4j/impl/StaticLoggerBinder.class");
-
检查是否存在多个绑定
如果类路径中存在多个StaticLoggerBinder
类文件,SLF4J 会输出警告信息,告诉用户存在多个日志框架绑定的情况。例如:SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [slf4j-log4j12-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [logback-classic-1.1.3.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [slf4j-jdk14-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
上述警告表示类路径中找到多个绑定,SLF4J 会随机选择一个日志框架进行绑定。最终的实际绑定类型会在警告中明确标示。
-
获取
StaticLoggerBinder
的单例
SLF4J 会通过StaticLoggerBinder.getSingleton()
方法获取StaticLoggerBinder
的单例实例。StaticLoggerBinder.getSingleton();
-
获取
ILoggerFactory
实例
从StaticLoggerBinder
的单例中,获取实际的ILoggerFactory
实例。StaticLoggerBinder.getSingleton().getLoggerFactory();
获取 Logger
的过程
ILoggerFactory
是一个工厂类,负责根据指定的名称返回 Logger
实例。它的实现类(例如 Log4jLoggerFactory
, LogbackLoggerFactory
)根据所绑定的日志框架不同返回不同类型的 Logger
。
public interface ILoggerFactory {
Logger getLogger(String name);
}
SLF4J 与底层日志框架的集成
SLF4J 的设计允许它与多种底层日志框架进行集成。通常,SLF4J 会提供 org/slf4j/impl/StaticLoggerBinder.class
类来绑定一个具体的日志框架(如 log4j
或 logback
)。以下是 SLF4J 如何与常见的日志框架集成的原理:
-
Logback 集成
SLF4J 默认与logback
集成。logback-classic
包含了StaticLoggerBinder
类,该类会返回一个LogbackLoggerFactory
实例,进一步返回LogbackLogger
。 -
Log4j 集成
如果类路径中包含slf4j-log4j12
包,SLF4J 会将日志记录请求转发给Log4j
,而StaticLoggerBinder
会返回Log4jLoggerFactory
实例。 -
多个绑定警告
如果类路径中包含多个日志框架的绑定(如logback
和log4j
),SLF4J 会随机选择其中一个框架进行绑定。这个选择是由 JVM 的类加载机制决定的,并且会在控制台输出警告。
小结
- SLF4J 通过
StaticLoggerBinder
类在运行时决定与哪个底层日志框架(如logback
或log4j
)绑定。 LoggerFactory.getLogger()
会通过ILoggerFactory
获取具体的Logger
实例,这个过程包括查找StaticLoggerBinder
类并获取其单例。- SLF4J 允许同时存在多个日志框架的绑定,但只会选择其中一个,并通过警告通知用户存在多个绑定的情况。
- 在 SLF4J 中,日志框架的选择是通过类路径中
StaticLoggerBinder
类的存在与否来决定的,最终的日志实现由LoggerFactory
返回的Logger
实例确定。