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

slf4j+logback源码加载流程解析

slf4j绑定logback源码解析

Logger log = LoggerFactory.getLogger(LogbackDemo.class);

如上述代码所示,在项目中通常会这样创建一个Logger对象去打印日志。
然后点进去,会走到LoggerFactory的getILoggerFactory()方法,如下代码所示。

	public static ILoggerFactory getILoggerFactory() {if (INITIALIZATION_STATE == UNINITIALIZED) {synchronized (LoggerFactory.class) {if (INITIALIZATION_STATE == UNINITIALIZED) {INITIALIZATION_STATE = ONGOING_INITIALIZATION;performInitialization();}}}switch (INITIALIZATION_STATE) {case SUCCESSFUL_INITIALIZATION:return StaticLoggerBinder.getSingleton().getLoggerFactory();case NOP_FALLBACK_INITIALIZATION:return NOP_FALLBACK_FACTORY;case FAILED_INITIALIZATION:throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);case ONGOING_INITIALIZATION:// support re-entrant behavior.// See also http://jira.qos.ch/browse/SLF4J-97return SUBST_FACTORY;}throw new IllegalStateException("Unreachable code");}

performInitialization()方法表示执行初始化,点进去会调用到LoggerFactory的bind()方法,如下代码所示。

			Set<URL> staticLoggerBinderPathSet = null;if (!isAndroid()) {// 查找org/slf4j/impl/StaticLoggerBinder.class这个类的路径staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();// 如果有多个则打印Class path contains multiple SLF4J bindingsreportMultipleBindingAmbiguity(staticLoggerBinderPathSet);}// StaticLoggerBinder类是各个日志框架提供的,比如logback,如下图所示StaticLoggerBinder.getSingleton();INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;reportActualBinding(staticLoggerBinderPathSet);fixSubstituteLoggers();replayEvents();// release all resources in SUBST_FACTORYSUBST_FACTORY.clear();

在这里插入图片描述
StaticLoggerBinder类加载时会执行初始化,如下代码所示。

	static {SINGLETON.init();}void init() {try {try {// 这里会完成logback的自动配置new ContextInitializer(defaultLoggerContext).autoConfig();} catch (JoranException je) {Util.report("Failed to auto configure default logger context", je);}// logback-292if (!StatusUtil.contextHasStatusListener(defaultLoggerContext)) {StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext);}contextSelectorBinder.init(defaultLoggerContext, KEY);initialized = true;} catch (Exception t) { // see LOGBACK-1159Util.report("Failed to instantiate [" + LoggerContext.class.getName() + "]", t);}}

logback源码解析

ContextInitializer.autoConfig()方法源码如下:

    public void autoConfig() throws JoranException {StatusListenerConfigHelper.installIfAsked(loggerContext);// 查找配置文件,优先级:系统属性logback.configurationFile > logback-test.xml > logback.xmlURL url = findURLOfDefaultConfigurationFile(true);if (url != null) {configureByResource(url);} else {// 使用java的spi机制,查找Configurator的实现,如果有,则自动配置logbackConfigurator c = EnvUtil.loadFromServiceLoader(Configurator.class);if (c != null) {try {c.setContext(loggerContext);c.configure(loggerContext);} catch (Exception e) {throw new LogbackException(String.format("Failed to initialize Configurator: %s using ServiceLoader", c != null ? c.getClass().getCanonicalName() : "null"), e);}} else {// 使用默认的BasicConfigurator来自动配置logbackBasicConfigurator basicConfigurator = new BasicConfigurator();basicConfigurator.setContext(loggerContext);basicConfigurator.configure(loggerContext);}}}

spring boot初始化logback流程

Spring Boot启动的时候,由org.springframework.boot.context.logging.LoggingApplicationListener根据情况初始化并使用。

在spring 初始化启动的过程中,会根据生命周期的不同阶段,发出对应的动作。这就是Spring ApplicationListener,设计基于观察者模式,而其中LoggingApplicationListener类便是负责logging日志框架的初始化操作。

LoggingApplicationListener被配置在spring-boot-x.x.x.jar的spring.factories文件中,spring启动的时候会去读取这个文件。

LoggingApplicationListener.onApplicationEvent()方法源码如下。

	public void onApplicationEvent(ApplicationEvent event) {if (event instanceof ApplicationStartingEvent) {onApplicationStartingEvent((ApplicationStartingEvent) event);}else if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);}else if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent((ApplicationPreparedEvent) event);}else if (event instanceof ContextClosedEvent&& ((ContextClosedEvent) event).getApplicationContext().getParent() == null) {onContextClosedEvent();}else if (event instanceof ApplicationFailedEvent) {onApplicationFailedEvent();}}

第一个事件就是ApplicationStartingEvent了,点进去到LoggingSystem.get()方法。
在这里插入图片描述

在这里插入图片描述
因此,最终返回出去的是LogbackLoggingSystem对象,然后执行loggingSystem.beforeInitialize()方法,beforeInitialize会使用到logback的StaticLoggerBinder类,因此会读取logback.xml完成logback的初始化。

第二个事件是ApplicationEnvironmentPreparedEvent,会执行日志系统的初始化。

	protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {new LoggingSystemProperties(environment).apply();this.logFile = LogFile.get(environment);if (this.logFile != null) {this.logFile.applyToSystemProperties();}this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS);initializeEarlyLoggingLevel(environment);initializeSystem(environment, this.loggingSystem, this.logFile);initializeFinalLoggingLevels(environment, this.loggingSystem);registerShutdownHookIfNecessary(environment, this.loggingSystem);}// 主要看initializeSystem方法private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system, LogFile logFile) {LoggingInitializationContext initializationContext = new LoggingInitializationContext(environment);// 如果application.yml里指定了logging.config,则使用指定的文件初始化,否则按默认处理String logConfig = environment.getProperty(CONFIG_PROPERTY);if (ignoreLogConfig(logConfig)) {system.initialize(initializationContext, null, logFile);}else {try {ResourceUtils.getURL(logConfig).openStream().close();system.initialize(initializationContext, logConfig, logFile);}catch (Exception ex) {// NOTE: We can't use the logger here to report the problemSystem.err.println("Logging system failed to initialize using configuration from '" + logConfig + "'");ex.printStackTrace(System.err);throw new IllegalStateException(ex);}}}// 下面会走到LogbackLoggingSystem.initialize()方法public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {LoggerContext loggerContext = getLoggerContext();if (isAlreadyInitialized(loggerContext)) {return;}super.initialize(initializationContext, configLocation, logFile);loggerContext.getTurboFilterList().remove(FILTER);markAsInitialized(loggerContext);if (StringUtils.hasText(System.getProperty(CONFIGURATION_FILE_PROPERTY))) {getLogger(LogbackLoggingSystem.class.getName()).warn("Ignoring '" + CONFIGURATION_FILE_PROPERTY+ "' system property. Please use 'logging.config' instead.");}}// 再到AbstractLoggingSystem.initialize()方法public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {if (StringUtils.hasLength(configLocation)) {initializeWithSpecificConfig(initializationContext, configLocation, logFile);return;}initializeWithConventions(initializationContext, logFile);}// 再到initializeWithConventions方法private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile) {// 查找logback自己的配置文件logback-test.xml、logback.xmlString config = getSelfInitializationConfig();if (config != null && logFile == null) {// logback在前面第一次使用StaticLoggerBinder时已经完成了初始化,这里会重新初始化一次reinitialize(initializationContext);return;}if (config == null) {// 获取logback-spring.xmlconfig = getSpringInitializationConfig();}if (config != null) {// 加载配置logback-spring.xmlloadConfiguration(initializationContext, config, logFile);return;}// 加载默认配置loadDefaults(initializationContext, logFile);}// reinitialize方法会走到LogbackLoggingSystem.configureByResourceUrl()方法,这里使用了SpringBootJoranConfiguratorprivate void configureByResourceUrl(LoggingInitializationContext initializationContext, LoggerContext loggerContext,URL url) throws JoranException {if (url.toString().endsWith("xml")) {JoranConfigurator configurator = new SpringBootJoranConfigurator(initializationContext);configurator.setContext(loggerContext);configurator.doConfigure(url);}else {// 否则使用logback的ContextInitializer进行初始化,这就不支持springProperty标签new ContextInitializer(loggerContext).configureByResource(url);}}// SpringBootJoranConfigurator添加了额外的规则,如springProperty标签class SpringBootJoranConfigurator extends JoranConfigurator {@Overridepublic void addInstanceRules(RuleStore rs) {super.addInstanceRules(rs);Environment environment = this.initializationContext.getEnvironment();rs.addRule(new ElementSelector("configuration/springProperty"), new SpringPropertyAction(environment));rs.addRule(new ElementSelector("*/springProfile"), new SpringProfileAction(environment));rs.addRule(new ElementSelector("*/springProfile/*"), new NOPAction());}}

相关文章:

slf4j+logback源码加载流程解析

slf4j绑定logback源码解析 Logger log LoggerFactory.getLogger(LogbackDemo.class);如上述代码所示&#xff0c;在项目中通常会这样创建一个Logger对象去打印日志。 然后点进去&#xff0c;会走到LoggerFactory的getILoggerFactory()方法&#xff0c;如下代码所示。 public …...

KVM虚拟机部署K8S重启后/etc/hosts内容丢失

前言 使用KVM开了虚拟机部署K8S&#xff0c;部署完成后重启&#xff0c;节点的pod等信息无法获取到&#xff0c;查看报错初步推测为域名解析失效&#xff0c;查看/etc/hosts后发现安装k8s时添加的内容全部消失 网上搜索一番之后发现了 如果直接修改 /etc/hosts 文件&#xff0…...

Redis使用场景(五)

Redis实战精讲-13小时彻底学会Redis 1.计数器 可以对 String 进行自增自减运算&#xff0c;从而实现计数器功能。 Redis 这种内存型数据库的读写性能非常高&#xff0c;很适合存储频繁读写的计数量。 2.缓存 将热点数据放到内存中&#xff0c;设置内存的最大使用量以及淘汰策略…...

【UnityShader入门精要学习笔记】(2)GPU流水线

本系列为作者学习UnityShader入门精要而作的笔记&#xff0c;内容将包括&#xff1a; 书本中句子照抄 个人批注项目源码一堆新手会犯的错误潜在的太监断更&#xff0c;有始无终 总之适用于同样开始学习Shader的同学们进行有取舍的参考。 文章目录 上节复习GPU流水线顶点着色…...

CSS免费在线字体格式转换器 CSS @font-face 生成器

今天竟意外发现的一款免费的“网页字体生成器”&#xff0c;功能强大又好用~ 工具地址&#xff1a;https://transfonter.org/ 根据你设置生成后的文件预览&#xff1a; 支持TTF、OTF、WOFF、WOFF2 或 SVG字体格式转换生成&#xff0c;每个文件最大15MB。转换完成以后还会生成一…...

Codeium在IDEA里的3个坑

转载自Codeium在IDEA里的3个坑&#xff1a;无法log in&#xff0c;downloading language server和中文乱码_downloading codeium language server...-CSDN博客文章浏览阅读1.7w次&#xff0c;点赞26次&#xff0c;收藏47次。Codeium安装IDEA插件的3个常见坑_downloading codeiu…...

C-C++ 项目构建指南:如何使用 Makefile 提高开发效率

Makefile是一个常用的自动化构建工具&#xff0c;它可以为开发人员提供方便的项目构建方式。在C/C项目中&#xff0c;Makefile可以用来编译、链接和生成可执行文件。使用Makefile的好处是可以自动执行一系列命令&#xff0c;从而减少手动操作的复杂性和出错的可能性。此外&…...

基于SpringBoot的图书管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 🚀🚀🚀SpringBoot 阿博图书管理系…...

矩阵对角线遍历

Diagonal 2614. 对角线上的质数 class Solution {public int diagonalPrime(int[][] nums) {int n = nums....

【教程】Typecho Joe主题开启并修复壁纸相册不显示问题

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 背景说明 Joe主题本身支持“壁纸”功能&#xff0c;其实就是相册。当时还在网上找了好久相册部署的开源项目&#xff0c;太傻了。 但是网上教程很少&#xff0c;一没说如何开启壁纸功能&#xff0c;二没说开启后为…...

MR混合现实情景实训教学系统在法律专业课堂上的应用

MR混合现实情景实训教学系统是一种将虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;相结合的先进技术。在法律教学课堂上&#xff0c;MR教学系统为学生模拟模拟法庭、案例分析等多种形式&#xff0c;让学生在实践中掌握法律知识&#xff0c;提高法律…...

车载 Android之 核心服务 - CarPropertyService 的VehicleHAL

前言: 本文是车载Android之核心服务-CarPropertyService的第二篇&#xff0c;了解一下CarPropertyService的VehicleHAL, 第一篇在车载 Android之 核心服务 - CarPropertyService 解析-CSDN博客&#xff0c;有兴趣的 朋友可以去看下。 本节介绍 AndroidAutomotiveOS中对于 Veh…...

年底了,准备跳槽的可以看看...

前两天跟朋友感慨&#xff0c;今年的铜九铁十、裁员、疫情导致好多人都没拿到offer!现在已经1月了&#xff0c;具体明年的金三银四只剩下两个月。 对于想跳槽的职场人来说&#xff0c;绝对要从现在开始做准备了。这时候&#xff0c;很多高薪技术岗、管理岗的缺口和市场需求也出…...

Bagging算法_随机森林Random_Forest

Bagging B a g g i n g Bagging Bagging是并行式集成学习方法最著名的代表&#xff0c;这个名字是由 B o o t s t r a p A G G r e g a t I N G Bootstrap AGGregatING BootstrapAGGregatING而来&#xff0c;顾名思义&#xff0c;该算法由 B o o s t s t r a p Booststrap Boos…...

物理与网络安全

物流环境安全 场地选择考虑抗震、承重、防火、防水、供电、空气调节、电磁防护、雷击及静电 场地因素&#xff1a; 自然灾害&#xff0c;社会因素&#xff08;加油站、化工厂&#xff09;&#xff0c;配套条件&#xff08;消防&#xff0c;交通&#xff0c;电力&#xff0c;…...

torch.meshgrid和np.meshgrid的区别

numpy中meshgrid&#xff1a; 把数组a当作一行&#xff0c;再根据数组b的长度扩充行。 把数组b当作一列&#xff0c;再根据数组a的长度扩充列。 torch中meshgrid&#xff1a; 把数组a当作一列&#xff0c;再根据数组b的长度扩充列。 把数组b当作一行&#xff0c;再根据数组a的…...

【PostgreSQL】约束-唯一约束

【PostgreSQL】约束链接 检查 唯一 主键 外键 排他 唯一约束 唯一约束是数据库中的一种约束&#xff0c;用于确保某个列或字段的值在该列或字段中是唯一的。唯一约束可用于确保数据库表中的某个列中的值是唯一的&#xff0c;也可用于确保多个列的组合值是唯一的。 在创建表…...

学习使用js/jquery获取指定class名称的三种方式

学习使用js/jquery获取指定class名称的三种方式 简介一、获取元素的class名称1、通过原生JS获取元素的class名称2、通过Jquery获取元素的class名称 二、应用1、样式修改2、动画效果实现 简介 在开发网页时&#xff0c;我们经常需要通过JS获取元素的class名称进行一些操作&…...

latex数学公式

写于&#xff1a;2024年1月5日 晚 修改&#xff1a; 摘要&#xff1a;数学公式根据其位置可以分为行内公式和行间公式。行内公式更加紧凑&#xff0c;而行间公式富于变化&#xff0c;可以为其编号、引用、换行等操作。本文对数学公式的 LaTex 做简单记录和整理。 行内公式 行内…...

frp配置内网穿透访问家里的nas

frp配置内网穿透访问家里的nas 需求 家里局域网内有台nas&#xff0c;在去公司的路上想访问它 其内网地址为&#xff1a; http://192.168.50.8:6002 工具 1.frp版本v0.53.2 下载地址&#xff1a; https://github.com/fatedier/frp/releases/download/v0.53.2/frp_0.53.2_li…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...

【Ftrace 专栏】Ftrace 参考博文

ftrace、perf、bcc、bpftrace、ply、simple_perf的使用Ftrace 基本用法Linux 利用 ftrace 分析内核调用如何利用ftrace精确跟踪特定进程调度信息使用 ftrace 进行追踪延迟Linux-培训笔记-ftracehttps://www.kernel.org/doc/html/v4.18/trace/events.htmlhttps://blog.csdn.net/…...

C/Python/Go示例 | Socket Programing与RPC

Socket Programming介绍 Computer networking这个领域围绕着两台电脑或者同一台电脑内的不同进程之间的数据传输和信息交流&#xff0c;会涉及到许多有意思的话题&#xff0c;诸如怎么确保对方能收到信息&#xff0c;怎么应对数据丢失、被污染或者顺序混乱&#xff0c;怎么提高…...