当前位置: 首页 > news >正文

logback日志框架源码分析

目录

(一)入口:slf4j选择日志框架

(二)日志框架初始化

(1)logback的3种配置方式

a、BasicConfigurator默认配置

b、SPI方式配置的Configurator实现类

c、通过配置文件初始化

(2)xml配置文件初始化

(三)Logger的创建

(四)打印日志


本文源码基于:logback版本:1.2.11

在我们使用logback日志框架时,通常都会通过配置logback.xml定制化我们的日志需求。但你是否对loback日志如何加载配置感到好奇?如果没有logback.xml,logback的默认配置又是什么样的?配置文件中定义的appender和logger又是什么关系呢?在这一篇章我们会通过深入logback源码进行分析

(一)入口:slf4j选择日志框架

logback也是基于slf4j的一个日志框架实现。可以从maven的依赖中可以看到logback-classic依赖了slf4j-api。

 所以我们使用logback日志也是使用slf4j的接口:

private static final Logger logger = LoggerFactory.getLogger(LogTest.class);

而日志的配置加载就在首次调用LoggerFactory.getLogger时进行,具体是在LoggerFactory.getLogger-》getILoggerFactory():获取LoggerFactory时进行初始化,可以看到一个如下的performInitialization()方法。从名字可以看出这个方法就是去执行初始化的,而且使用状态位保证只初始化一次

我们接着看performInitialization方法中的bind方法:

我们知道slf4j只是定义了日志的接口,是一个日志接口协议。它将具体的日志框架实现交给各个日志框架,比如log4j2、logback等主流日志框架。这样在使用的时候,我们都是统一使用slf4j的接口,如果我们需要替换日志框架,那么只需要切换依赖,以及加上对应日志框架的配置日志就行。而之所以切换如此丝滑,就在于slf4j内部实现了日志框架实现的自动发现,即上图标红位置。

它的自动发现也很简单,只是去查找org/slf4j/impl/StaticLoggerBinder.class这个类,这个就是slf4j和具体实现框架的一个约定。如果我们想自己实现一个基于slf4j的日志框架实现,那么首先我们就得提供这么一个静态日志绑定类。

上面只是发现静态日志绑定类,如果有多个(可能同时引入了多个slf4的日志实现框架),那么会输出错误日志到控制台。并没有实际发生任何绑定动作。

实际的绑定动作是执行StaticLoggerBinder.getSingleton();

这里哪个日志框架的StaticLoggerBinder类被调用,就实际用哪个日志框架实现。

(二)日志框架初始化

上面已经讲了slf4j如何选择日志框架,最终取决于StaticLoggerBinder是哪个日志框架,这也是logback 初始化的入。接下来讲讲logback实际的初始化。

StaticLoggerBinder将绑定ILoggerFactory,使用单例模式,通过StaticLoggerBinder.getSingleton().getLoggerFactory()获取ILoggerFactory对象。它的初始化是在静态代码块中调用单例的初始化方法:SINGLETON.init();

它初始化了一个ContextInitializer,并传入StaticLoggerBinder中的默认LoggerContext,所有的初始化配置都是LoggerContext管理,实际上getLoggerFactory也是返回的此对象,所以它实际也是logger的工厂类。之后调用autoConfig,进行配置。我们重点看一下autoConfig:

(1)logback的3种配置方式

从上述代码可以看到3种配置方式的选择顺序:一个是通过获取配置文件,如果没有配置文件,那么就尝试加载SPI方式配置的Configurator实现类。如果也没有,那么会使用默认BasicConfigurator。三种配置都有两个关键步骤:

configurator.setContext(loggerContext);
configurator.doConfigure(loggerContext);

首先设置日志上下文,因为所有的配置都是围绕上下文的,所以它是配置器不可或缺的。第二步就是调用doConfigure,执行上下文执行实际的配置。

下面我们从简单到复杂一一介绍:

a、BasicConfigurator默认配置

默认配置很简单:

将ConsoleAppender附加到root logger,ConsoleAppender的layout设置为TTLLLayout,它等同于%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"。所以它等同于使用如下配置文件:

<configuration><!-- Appenders --><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- Root Logger --><root><appender-ref ref="CONSOLE"/></root>
</configuration>

日志级别没有指定,默认是debug级别

相关文章:

logback日志框架源码分析

目录 (一)入口:slf4j选择日志框架 (二)日志框架初始化 (1)logback的3种配置方式 a、BasicConfigurator默认配置 b、SPI方式配置的Configurator实现类 c、通过配置文件初始化 (2)xml配置文件初始化 (三)Logger的创建 (四)打印日志 本文源码基于:logback版…...

【微服务】3、配置管理

微服务配置管理 已掌握的微服务组件及配置管理问题引出 已掌握注册中心、Openfan、远程调用、负载均衡、网关等组件&#xff0c;具备微服务开发能力&#xff0c;但仍存在其他问题待解决。微服务和网关存在大量配置文件&#xff0c;其中包含很多重复配置&#xff0c;如数据库、日…...

数据分析思维(七):分析方法——群组分析方法

数据分析并非只是简单的数据分析工具三板斧——Excel、SQL、Python&#xff0c;更重要的是数据分析思维。没有数据分析思维和业务知识&#xff0c;就算拿到一堆数据&#xff0c;也不知道如何下手。 推荐书本《数据分析思维——分析方法和业务知识》&#xff0c;本文内容就是提取…...

概述(讲讲python基本语法和第三方库)

我是北子&#xff0c;这是我自己写的python教程&#xff0c;主要是记录自己的学习成果方便自己日后复习&#xff0c; 我先学了C/C&#xff0c;所以这套教程中可能会将很多概念和C/C去对比&#xff0c;所以该教程大概不适合零基础的人。 it seems that python nowadays 只在人工…...

力扣-20-有效的括号-栈

思路&#xff1a; 左括号每次匹配都是先匹配最后进来的&#xff0c;和栈的特点很相似&#xff0c;我们就可以利用栈来完成...

数据在内存中的存储【C语言版】

目录 1.举例&#xff1a; 2.深入刨析大端小端的组成&#xff1a; 3.判断当前编译环境是大端还是小端的方法 4.以函数的形式来判断当前的编译环境是大端还是小端【就是把判断大端小端的方法放进函数里面来实现&#xff0c;得到返回值&#xff0c;可以减少main()函数的内存】…...

【SQL】进阶知识 — 各大数据库合并几条数据到一行的方式

大家好&#xff0c;欢迎来到本期的 SQL 知识分享&#xff01;今天我们要聊一个非常实用的技能&#xff1a;如何将多个行数据合并成一行&#xff01;如果你曾经需要把多个查询结果合并成一个单元&#xff0c;或者把多行数据汇总到一个字段中&#xff0c;这篇文章将会教你如何用 …...

Gitee上传项目代码教程(详细)

工具必备&#xff1a;Git Bash 上传步骤 1.在Gitee创建项目仓库 2.进入本地项目目录 右键打开Git Bash here 3.配置用户名和邮箱 如果之前给git配置过用户名和邮箱可跳过 查看Git是否配置成功&#xff1a;git config --list git config --global user.name "xxx"…...

python ijson 用法教程

ijson PyPI Python ijson处理大型JSON文件 - 秀尊云 Python解析JSON大文件 | Leetaos Blog https://stackoverflow.com/questions/2400643/is-there-a-memory-efficient-and-fast-way-to-load-big-json-files/58148422#58148422 Python中读写&#xff08;解析&#xff09;J…...

什么是网络安全攻防演练,即红蓝对抗?

定义与目的 定义&#xff1a;网络安全攻防演练是一种模拟真实网络攻击和防御场景的活动&#xff0c;通过组织专业的攻击队伍&#xff08;红队&#xff09;和防御队伍&#xff08;蓝队&#xff09;进行对抗&#xff0c;来检验和提升组织的网络安全防御能力、应急响应能力和安全运…...

数据挖掘——决策树分类

数据挖掘——决策树分类 决策树分类Hunt算法信息增益增益比率基尼指数连续数据总结 决策树分类 树状结构&#xff0c;可以很好的对数据进行分类&#xff1b; 决策树的根节点到叶节点的每一条路径构建一条规则&#xff1b;具有互斥且完备的特点&#xff0c;即每一个样本均被且…...

Pytorch单、多GPU和CPU训练模型保存和加载

Pytorch多GPU训练模型保存和加载 在多GPU训练中&#xff0c;模型通常被包装在torch.nn.DataParallel或torch.nn.parallel.DistributedDataParallel中&#xff0c;这会在模型的参数名前加上module前缀。因此&#xff0c;在保存模型时&#xff0c;需要使用model.module.state_di…...

Karate 介绍与快速示例(API测试自动化、模拟、性能测试与UI自动化工具)

Karate是一个将API测试自动化、模拟、性能测试甚至UI自动化结合到一个统一框架中的开源工具。 Karate使用Gherkin 的BDD语法,是语言中性的,即使是非程序员也很容易。断言和HTML报告是内置的,支持并行运行测试以提高速度Karate 是用Java语言编写, 可以在Java 项目项目中运行…...

Pytest 高级用法:间接参数化

文章目录 1. 引言2. 基础概念2.1 Fixture2.2 参数化 3. 代码实例3.1 基础设置3.2 测试用例示例示例 1&#xff1a;基础的间接参数化示例 2&#xff1a;通过 request 获取参数值示例 3&#xff1a;多参数组合测试示例 4&#xff1a;部分间接参数化 4. 最佳实践5. 总结参考资料 1…...

第07章 存储管理(一)

一、磁盘简介 1.1 名称称呼 磁盘/硬盘/disk是同一个东西&#xff0c;不同于内存的是容量比较大。 1.2 类型 机械&#xff1a;机械硬盘即是传统普通硬盘&#xff0c;主要由&#xff1a;盘片&#xff0c;磁头&#xff0c;盘片转轴及控制电机&#xff0c;磁头控制器&#xff0…...

Go语言的 的设计模式(Design Patterns)核心知识

Go语言的设计模式&#xff08;Design Patterns&#xff09;核心知识 Go语言&#xff08;Golang&#xff09;是一种静态类型、编译型的编程语言&#xff0c;自2009年由Google正式推出以来&#xff0c;因其高效的性能、卓越的并发能力以及简洁的语法受到广泛欢迎。在软件开发中&…...

js函数预览图片:支持鼠标和手势拖拽缩放

对之前的方式改进&#xff1a;原生js实现图片预览控件&#xff0c;支持丝滑拖拽&#xff0c;滚轮放缩&#xff0c;放缩聚焦_js图片预览-CSDN博客 /*** 图片预览函数&#xff0c;调用后自动预览图片* param {图片地址} imgurl*/ function openImagePreview(imgurl) {if (!imgurl…...

用QT实现 端口扫描工具1

安装在线QT&#xff0c;尽量是完整地自己进行安装&#xff0c;不然会少包 参考【保姆级图文教程】QT下载、安装、入门、配置VS Qt环境-CSDN博客 临时存储空间不够。 Windows系统通常会使用C盘来存储临时文件。 修改临时文件存储位置 打开系统属性&#xff1a; 右键点击“此电…...

设计模式 结构型 适配器模式(Adapter Pattern)与 常见技术框架应用 解析

适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将一个类的接口转换成客户端所期望的另一个接口&#xff0c;从而使原本因接口不兼容而无法一起工作的类能够协同工作。这种设计模式在软件开发中非常有用&#xff0c;尤其是在需要集成…...

vue 项目集成 electron 和 electron 打包及环境配置

vue electron 开发桌面端应用 安装 electron npm i electron -D记得加上-D&#xff0c;electron 需添加到devDependencies&#xff0c;如果添加到dependencies后面运行可能会报错 根目录创建electron文件夹&#xff0c;在electron文件夹创建main.js&#xff08;或者backgrou…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...