SpringBoot源码阅读(7)——日志系统加载

SpringBoot的日志系统是在监听器中加载的。
SpringApplication的实例方法run,第298行。

listeners.starting(bootstrapContext, this.mainApplicationClass);

最终触发了监听器LoggingApplicationListener

具体方法逻辑

private void onApplicationStartingEvent(ApplicationStartingEvent event) {this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());this.loggingSystem.beforeInitialize();
}
public static final String SYSTEM_PROPERTY = LoggingSystem.class.getName();
private static final LoggingSystemFactory SYSTEM_FACTORY = LoggingSystemFactory.fromSpringFactories();
public static LoggingSystem get(ClassLoader classLoader) {String loggingSystemClassName = System.getProperty(SYSTEM_PROPERTY);if (StringUtils.hasLength(loggingSystemClassName)) {if (NONE.equals(loggingSystemClassName)) {return new NoOpLoggingSystem();}return get(classLoader, loggingSystemClassName);}LoggingSystem loggingSystem = SYSTEM_FACTORY.getLoggingSystem(classLoader);Assert.state(loggingSystem != null, "No suitable logging system located");return loggingSystem;
}

先从环境变量中获取日志配置。
如果有,就用这个全限定类名作为日志系统实例化这个日志系统。
这个类必须是LoggingSystem的子类,否则会报异常。如-Dorg.springframework.boot.logging.LoggingSystem=xxx.xx.xx.XxxLogSystem
如果没有,则从类路径中寻找LoggingSystemFactory的实现类

static LoggingSystemFactory fromSpringFactories() {return new DelegatingLoggingSystemFactory((classLoader) -> SpringFactoriesLoader.loadFactories(LoggingSystemFactory.class, classLoader));
}

LoggingSystemFactory的实现类有

# Logging Systems
org.springframework.boot.logging.LoggingSystemFactory=\
org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,\
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,\
org.springframework.boot.logging.java.JavaLoggingSystem.Factory

加载后排序,三个类都是被Order注解的

日志系统Order
LogbackLoggingSystem.FactoryInteger.MAX_VALUE
LogbackLoggingSystem.FactoryInteger.MAX_VALUE
LogbackLoggingSystem.FactoryInteger.MAX_VALUE
最后顺序是
  1. LogbackLoggingSystem.Factory
  2. Log4J2LoggingSystem.Factory
  3. JavaLoggingSystem.Factory

之后在DelegatingLoggingSystemFactorygetLoggingSystem方法中获取日志系统。

@Override
public LoggingSystem getLoggingSystem(ClassLoader classLoader) {List<LoggingSystemFactory> delegates = (this.delegates != null) ? this.delegates.apply(classLoader) : null;if (delegates != null) {for (LoggingSystemFactory delegate : delegates) {LoggingSystem loggingSystem = delegate.getLoggingSystem(classLoader);if (loggingSystem != null) {return loggingSystem;}}}return null;
}

从这里可以看出,三个日志系统的优先级顺序:logback > log4j2 > java log

LoggingSystemFactory.Factory

@Order(Ordered.LOWEST_PRECEDENCE)
public static class Factory implements LoggingSystemFactory {private static final boolean PRESENT = ClassUtils.isPresent("ch.qos.logback.classic.LoggerContext",Factory.class.getClassLoader());@Overridepublic LoggingSystem getLoggingSystem(ClassLoader classLoader) {if (PRESENT) {return new LogbackLoggingSystem(classLoader);}return null;}}

判断类路径中是否有ch.qos.logback.classic.LoggerContext,有的话,就创建一个LogbackLoggingSystem对象返回。
默认返回null。

Log4J2LoggingSystem.Factory

@Order(Ordered.LOWEST_PRECEDENCE)
public static class Factory implements LoggingSystemFactory {private static final boolean PRESENT = ClassUtils.isPresent("org.apache.logging.log4j.core.impl.Log4jContextFactory", Factory.class.getClassLoader());@Overridepublic LoggingSystem getLoggingSystem(ClassLoader classLoader) {if (PRESENT) {return new Log4J2LoggingSystem(classLoader);}return null;}}

判断类路径中是否有org.apache.logging.log4j.core.impl.Log4jContextFactory,如果有,就实例化一个Log4J2LoggingSystem对象
默认返回null。

JavaLoggingSystem.Factory

@Order(Ordered.LOWEST_PRECEDENCE)
public static class Factory implements LoggingSystemFactory {private static final boolean PRESENT = ClassUtils.isPresent("java.util.logging.LogManager",Factory.class.getClassLoader());@Overridepublic LoggingSystem getLoggingSystem(ClassLoader classLoader) {if (PRESENT) {return new JavaLoggingSystem(classLoader);}return null;}}

判断路径中是否存在java.util.logging.LogManager,如果存在,就实例化一个JavaLoggingSystem类。
默认返回null。

不出异常的话,最后总会得到一个日志系统。
然后调用日志系统的beforeInitialize方法。

初始化

LogbackLoggingSystem

@Override
public void beforeInitialize() {LoggerContext loggerContext = getLoggerContext();if (isAlreadyInitialized(loggerContext)) {return;}super.beforeInitialize();loggerContext.getTurboFilterList().add(FILTER);
}
private LoggerContext getLoggerContext() {ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory();Assert.isInstanceOf(LoggerContext.class, factory,() -> String.format("LoggerFactory is not a Logback LoggerContext but Logback is on "+ "the classpath. Either remove Logback or the competing "+ "implementation (%s loaded from %s). If you are using "+ "WebLogic you will need to add 'org.slf4j' to "+ "prefer-application-packages in WEB-INF/weblogic.xml",factory.getClass(), getLocation(factory)));return (LoggerContext) factory;
}

获取LoggerContext并初始化,具体逻辑是在slf4j,这里不展开。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/44085.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode热题100刷题10:46. 全排列、78. 子集、17. 电话号码的字母组合、39. 组合总和、138. 随机链表的复制

回溯问题 46. 全排列 全排列问题&#xff1a; path 递归终止条件&#xff1a;path中是否已存储所有元素&#xff1b; for循环处理节点集合&#xff1a;used0未被使用的元素 class Solution { public:vector<int> path;vector<vector<int>> res;void backt…

【MPPT太阳能升压控制器方案】远翔升压恒流驱动芯片FP7209单节电池升压24V,30V,36V,42V,48V全系列方案,高转换效率,输出带短路保护功能

高转换效率&#xff0c;太阳能控制器方案——详解太阳能控制器PWM / MPPT极简方案其设计要点&#xff0c;升压30V&#xff0c;36V&#xff0c;42V&#xff0c;48V 使用单颗芯片FP7209即实现两级升压到30V&#xff0c;36V&#xff0c;42V&#xff0c;48V&#xff0c;相对于单极升…

RedHat运维-Ansible自动化运维基础26-管理用户与认证

1. user: 在所有受控主机上&#xff0c;新建一个用户Hello_Kitty&#xff0c;用户shell是/bin/bash&#xff0c;并将这个用户加入组wheel&#xff1b; 2. user: 在所有受控主机上&#xff0c;新建一个用户Kitty_bug&#xff0c;用户shell是/bin/bash&#xff0c;并将这个用户加…

【Python】已解决:ModuleNotFoundError: No module named ‘nltk’

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ModuleNotFoundError: No module named ‘nltk’ 一、分析问题背景 在使用Python进行自然语言处理或文本分析时&#xff0c;我们经常会用到各种库来辅助我们的工…

【转】-java多线程读写锁ReadWriteLock

Java多线程中读写锁ReadWriteLock的使用 该博客转载自​**lavimer​的​Java多线程中读写锁ReadWriteLock的使用** 1. 概念 读写锁分为读锁和写锁&#xff0c;多个读锁之间是不需要互斥的(读操作不会改变数据&#xff0c;如果上了锁&#xff0c;反而会影响效率)&#xff0c;…

【OpenCV】BGR三色通道的提取与合并--超详细解读

在OpenCV中&#xff0c;处理图像时经常需要提取或合并图像的RGB&#xff08;红、绿、蓝&#xff09;三色通道。OpenCV默认使用BGR&#xff08;蓝、绿、红&#xff09;顺序来存储图像的颜色通道&#xff0c;这一点与很多图像处理库&#xff08;如PIL/Pillow&#xff09;不同&…

Android Constant expression required (case R.id.xxx)

gradle更新到8.0后&#xff0c;遇到了这个报错 有两种解决方式&#xff1a; 1、在gradle.properties中添加下面代码 android.nonFinalResIdsfalse 2、使用if-else来判断 int id view.getId(); if (id R.id.setting_iv_back) {} else if (id R.id.setting_tv_clear) {}

大数据面试题之GreenPlum(1)

目录 介绍一下GreenPlum GreenPlum属于哪家公司的产品&#xff0c;简单说下发展历史 GreenPlum如何处理大数据 GreenPlum有哪些优势 GreenPlum的缺点有哪些 如何优化GreenPlum的性能 如何监控和分析GreenPlum的性能指标 Greenplum整体架构信息 说下Master主机与Segment…

Web知识库应用程序LibreKB

什么是 LibreKB &#xff1f; LibreKB 是一款知识库 Web 应用程序。免费、开源、自托管&#xff0c;基于 PHP/MySQL。 官方并没有 Docker 镜像&#xff0c;老苏这次图省事&#xff0c;并没有像往常一样构建一个镜像&#xff0c;而是基于 Docker 搭建了一个 LAMP 环境&#xff0…

判断一个字符串中出现次数最多的字符,统计这个次数?

1、核心算法&#xff1a;利用 charAt() 遍历这个字符串 2、把每个字符都存储给对象&#xff0c;如果对象没有该属性就为1&#xff0c;如果存了就1 3、遍历对象&#xff0c;得到最大值及出现次数和该字符 let str "aozisodsdkksdsd" let obj {} for (let i 0; i &l…

ConditionalOnJndi注解使用介绍、应用场景以及示例代码

概述 ConditionalOnJndi 是 Spring Framework 中的一个条件注解&#xff0c;用于在特定的 JNDI (Java Naming and Directory Interface) 环境条件下决定是否创建一个 bean 或配置一个 bean。JNDI 是 Java EE 规范中定义的一种用于访问命名和目录服务的 API&#xff0c;它允许 …

蹭一个围棋亚军!不要和低维的人说话——早读(逆天打工人爬取热门微信文章解读)

熬夜后需要补什么呢&#xff1f; 引言Python 代码第一篇 洞见 不要和低维的人说话&#xff08;深度好文&#xff09;第二篇 冲冲冲结尾 引言 昨晚真的是熬夜又想不出东西 真的头大 最近下围棋 这个棋感很好呀 我是K级选手 目前是8级 套几个buff 纯自学 为什么决定学围棋呢? 是…

谷粒商城配置中心错误记录

文章目录 一&#xff0c;com.alibaba.nacos.api.exception.NacosException: endpoint is blank1&#xff0c;分析定位2&#xff0c;关于配置文件application和bootstrap的区别与练习加载顺序使用说明 参考文献 一&#xff0c;com.alibaba.nacos.api.exception.NacosException: …

AI工具:软件开发者的革命性助手还是潜在威胁?

近年来&#xff0c;生成式人工智能&#xff08;AIGC&#xff09;在软件开发领域掀起了一场革命。从代码生成、错误检测到自动化测试&#xff0c;AI工具正在快速改变开发者的工作方式。这些工具不仅提高了开发效率&#xff0c;还引发了关于开发者职业前景和技能需求变化的广泛讨…

Navicat Premium 15 for Mac/Win 中文安装包下载

Navicat Premium 15 是一款数据库管理工具&#xff0c;它支持多种类型的数据库&#xff0c;包括 MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite。该软件提供了一个用户友好的图形界面&#xff0c;使得数据库的管理变得更加简单和高效。Navicat Premium 1…

chrony与ntp两种时钟同步方式对比

chrony 是一个用于网络时间同步的守护进程&#xff0c;设计用来替代传统的 ntpd&#xff08;Network Time Protocol Daemon&#xff09;。虽然两者都基于 NTP&#xff08;网络时间协议&#xff09;来同步系统时钟&#xff0c;但 chrony 在某些方面提供了改进和增强的功能&#…

Python数据分析实战,铁路站点客流量预测,案例教程编程实例课程详解

引言 铁路站点客流量预测是铁路运输管理和优化中的关键任务。准确的客流量预测可以帮助铁路部门提前调配资源,合理安排运力,提高运输效率,减少运营成本,同时提升乘客的出行体验。本文将介绍如何使用Python进行铁路站点客流量的预测,包括数据收集、预处理、模型构建、评估与…

网页视频提取在线工具

在互联网的海洋中&#xff0c;我们时常会遇到一些令人心动的视频&#xff0c;想要将其下载到本地&#xff0c;以便随时观看。然而&#xff0c;网页视频下载对于很多人来说&#xff0c;似乎是个复杂的过程。别担心&#xff0c;今天我就为大家带来一份详尽的网页视频下载教程&…

24小时悬停系留照明无人机技术详解

24小时悬停系留照明无人机是一款专门设计用于提供长时间、高效能照明服务的无人机系统。该系统结合了无人机技术与先进的照明设备&#xff0c;通过系留技术实现无人机的稳定悬停&#xff0c;从而提供连续不断的照明服务。该无人机能够在各种环境条件下进行24小时不间断工作&…

Zkeys三方登录模块支持QQ、支付宝登录

1&#xff0c;覆盖到根目录&#xff0c;并导入update.sql数据库文件到Zkeys数据库里 2. 后台系统权限管理&#xff0c;配置管理员权限-系统类别-找到云外科技&#xff0c;全部打勾 3&#xff0c;后台系统设置找到云外快捷登录模块填写相应的插件授权配置和登录权限配置&#x…