文章目录
- 官网
- 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实例确定。




















