Slf4j使用Logback时,Logback如何初始化

前言

Slf4j

SLF4J,全称 Simple Logging Facade for Java,是一个用于Java编程语言的日志系统抽象层。它为多种现有日志框架(例如Log4j、java.util.logging等)提供了统一的接口, 但自身并不实现日志功能。 SLF4J 允许用户在部署时选择适当的日志库(即日志框架),比如 Logback、Log4j 等。

Logback

Logback 是一个实现日志功能的库,它由Log4j的创建者设计。Logback被设计成Log4j的一个卓越替代品,它具有更好的性能、自动重加载配置文件、更丰富的日志格式以及内置日志归档等特点。 简单来说,SLF4J为Java提供了一个统一的日志接口,而Logback是一个具体的日志库,可以与SLF4J API结合起来使用。

注意,其它日志实现如log4j等结合slf4j的时候是需要桥接包,而logback是直接实现了slf4j。

Slf4j初始化源码分析

slf4j在代码中初始化一个Logger对象时,如下,调用LoggerFactory.getLogger()方法:

java 复制代码
private final Logger logger = LoggerFactory.getLogger(this.getClass());

查看getLogger方法:

java 复制代码
public static Logger getLogger(String name) {  
    // logback实现了slf4j的ILoggerFactory接口,关键也在于这个地方
    ILoggerFactory iLoggerFactory = getILoggerFactory();  
    return iLoggerFactory.getLogger(name);  
}

logback针对ILoggerFactory的实现类是:ch.qos.logback.classic.LoggerContext。 所以可以直接查看LoggerContext.getLogger()方法。 可以看到最终是调用到这个方法:

这个地方不是配方重点,这里分析下初始化的时候如何构造LoggerContext实例:

java 复制代码
 ILoggerFactory iLoggerFactory = getILoggerFactory();  

通过追踪方法调用,可以看到最终调用的是这个bind()方法(具体调用的源码细节,可以自己点进去看一下,代码不多,不啰嗦了):

java 复制代码
    private final static void bind() {
        try {
            Set<URL> staticLoggerBinderPathSet = null;
            // 不检查安卓系统的
            if (!isAndroid()) {
                 // 这里是找到所有org/slf4j/impl/StaticLoggerBinder.class的jar路径
                staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
                // 如果项目有多个日志框架的实现,平常启动项目不是会打印一些日志:Class path contains multiple SLF4J bindings.等
                // 就是这这个地方打印的,日志实现冲突
                reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
            }
            // 每个实现slf4j的日志或者桥接包都会有这个org/slf4j/impl/StaticLoggerBinder.class类
            StaticLoggerBinder.getSingleton();
            INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
            reportActualBinding(staticLoggerBinderPathSet);
        } catch (NoClassDefFoundError ncde) {
          // 下面代码忽略了
        } catch (java.lang.NoSuchMethodError nsme) {

        } catch (Exception e) {
            failedBinding(e);
            throw new IllegalStateException("Unexpected initialization failure", e);
        } finally {
            postBindCleanUp();
        }
    }

StaticLoggerBinder.getSingleton();这个注释里说了,每个实现或者桥接包都有这个类的,比如logback:

这个地方也是slf4j初始化的精髓,没有这个类就抛异常了。

而关于StaticLoggerBinder的初始化,也很平常:

就是通过静态代码块来初始化logback了。

相关推荐
AI人工智能+电脑小能手1 分钟前
【大白话说Java面试题】【Java基础篇】第30题:JDK动态代理和CGLIB动态代理有什么区别
java·开发语言·后端·面试·代理模式
swipe12 分钟前
别再把 AI 聊天做成纯文本:从 agui 这个前后端项目,拆解“可感知工具调用”的流式 AI UI
后端·langchain·llm
GetcharZp13 分钟前
GitHub 爆火!纯 Go 编写的文件同步神器 Syncthing,凭什么成为程序员的标配?
后端
hERS EOUS17 分钟前
SpringBoot 使用 spring.profiles.active 来区分不同环境配置
spring boot·后端·spring
DFT计算杂谈22 分钟前
wannier90 参数详解大全
java·前端·css·html·css3
LucianaiB28 分钟前
我用飞书多维表做了一个 AI 活动推荐智能体:每天自动催我别错过截止日期!
后端
marsh020632 分钟前
43 openclaw熔断与降级:保障系统在异常情况下的可用性
java·运维·网络·ai·编程·技术
张健115640964839 分钟前
临界区和同一线程上锁
java·开发语言·jvm
铁皮饭盒1 小时前
第2课:5分钟!用 Trae AI 生成你的第一个后端服务(Bunjs + Elysia)
前端·后端·全栈
超梦dasgg1 小时前
智慧充电系统设备管理服务对外接口实现方案
java·spring·微服务