java日志框架简介

文章目录

    • 概要
    • 常用日志框架
        • 常见框架有以下:
        • slf4j StaticLoggerBinder绑定过程(slf4j-api-1.7.32 )
        • JCL 运行时动态查找过程:(commons-logging-1.2)
        • 使用桥接修改具体日志实现
    • 一行日志的打印过程
    • 开源框架日志模块
        • Spring && Springboot
        • Mybatis

概要

文章简要梳理java常见日志框架,学习其背景和实现,通过阅读文章可以掌握如下知识点:
1、学习目前常用日志接口和实现框架,了解其功能作用实现原理。
2、掌握slf4j和logback的日志组合框架,debug跟踪一行日志的打印流程。
3、学习日常开发框架如Spring, Mybatis,了解大佬是如何实现日志模块。

常用日志框架

一、日志框架主要分为两类,日志门面接口和日志具体实现。

  1. 日志门面接口,如JCL 和 slf4j
    1)应用面向接口编程,接口不易变动。
    2)面向接口,可以通过绑定或桥接切换不同日志系统实现。
  2. 日志具体实现,如log4j JUL logback log4j2等。
    1)专注于实现日志打印功能实现。
    2)提供各种日志配置和功能特性。
常见框架有以下:
框架功能描述
log4j实现Apache 早期开源日志框架
JUL
java.util.logging
实现Sun官方自带日志框架,JDK1.4引入
JCL
Apache Commons Logging
接口Apache 的日志门面,可以切换log4j或JUL具体日志实现
slf4j-api接口简单java日志接口,日志门面,简单易用
logback实现高性能日志实现框架,包含一下模块:
logback-core:基础模块
logback-classic:日志实现模块
log4j2实现Apache 的开源日志框架,性能优化版本
slf4j-jcl
slf4j-jdk14
slf4j-log412
绑定slf4j-api具体绑定实现
jcl-over-slf4j
jul-to-slf4j
log4j-over-slf4j
桥接其他日志框架slf4j-api具体绑定实现

日志分层可参考如下图:
日志分层
绑定查找具体实现过程:

slf4j StaticLoggerBinder绑定过程(slf4j-api-1.7.32 )
  1. 如果未初始化,执行初始化:LoggerFactory#performInitialization。
  2. 扫描类文件:org/slf4j/impl/StaticLoggerBinder.class,报告不存在类或存在多个类歧义。
  3. 由具体实现框架提logback-classic提供StaticLoggerBinder,触发其静态绑定。

TIP:sl4j-api 2.x版本使用SPI org.slf4j.spi.SLF4JServiceProvider,
logback提供service实现 ch.qos.logback.classic.spi.LogbackServiceProvider

JCL 运行时动态查找过程:(commons-logging-1.2)
  1. System.getProperty读org.apache.commons.logging.LogFactory
  2. 读META-INF/services/org.apache.commons.logging.LogFactory
  3. 读取类路径下commons-logging.properties,key=org.apache.commons.logging.LogFactory
  4. 使用默认实现org.apache.commons.logging.impl.LogFactoryImpl,按下面顺序获取Logger:
    Log4JLogger
    Jdk14Logger
    Jdk13LumberjackLogger
    SimpleLog
使用桥接修改具体日志实现

如果项目依赖第三包已经其他日志框架接口,那么这时候如何规范化统一日志实现,这时候可以使用桥接:
桥接

一行日志的打印过程

下面介绍一行日志的打印过程,以目前市面常见搭配组合slf4j-api-1.7.32 logback-classic-1.2.12为例,代码只展示部分关键源码:
1、LoggerFactory#getLogger(Class<?> clazz),
获取指定名称Logger。

public static Logger getLogger(String name) {ILoggerFactory iLoggerFactory = getILoggerFactory();return iLoggerFactory.getLogger(name);
}

2、LoggerFactory#getILoggerFactory,
获取日志工厂LoggerFactory,如果未初始化则执行performInitialization完成日志实现绑定。

public static ILoggerFactory getILoggerFactory() {if (INITIALIZATION_STATE == UNINITIALIZED) {synchronized (LoggerFactory.class) {if (INITIALIZATION_STATE == UNINITIALIZED) {INITIALIZATION_STATE = ONGOING_INITIALIZATION;performInitialization();}}}……}

3、LoggerFactory#bind,
绑定到具体日志实现,扫描类路径资源文件org/slf4j/impl/StaticLoggerBinder.class,加载完成绑定。

private final static void bind() {staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);……
}

4、StaticLoggerBinder.getSingleton().getLoggerFactory(),
具体日志实现绑定初始化,如绑定到logback的StaticLoggerBinder,调用logback实现类StaticLoggerBinder#init->ContextInitializer#autoConfig,实现具体绑定类初始化。
logback ContextInitializer配置
1)ContextInitializer#configureByResource,按顺序检查如下配置文件logback-test.xml,logback.groovy,logback.xml,则存在使用配置文件。
2)SPI 加载是否指定Configurator配置实现,是则使用该配置实现。
3)如果上述都没有,则使用默认配置实现BasicConfigurator。

public ILoggerFactory getLoggerFactory() {public void autoConfig() throws JoranException {StatusListenerConfigHelper.installIfAsked(loggerContext);URL url = findURLOfDefaultConfigurationFile(true);if (url != null) {configureByResource(url);} else {Configurator 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 basicConfigurator = new BasicConfigurator();basicConfigurator.setContext(loggerContext);basicConfigurator.configure(loggerContext);}}}
}

5、LoggerContext#getLogger,
获取指定名称logger。

public final Logger getLogger(final String name) {……synchronized (logger) {childLogger = logger.getChildByName(childName);if (childLogger == null) {childLogger = logger.createChildByName(childName);loggerCache.put(childName, childLogger);incSize();}}……
}

6、Logger#info,
具体一行日志打印,以Info级别日志打印为例:

  1. 全局过滤器 TurboFilter判断是否打印
    2)构建LoggingEvent,将日志事件投递给Appender#doAppend
    3)调用Appender配置过滤Filter判断是否打印
    4)交给具体Appender完成日志事件处理,实现有:
    控制台ConsoleAppender
    文件FileAppender
    归档文件RollingFileAppender
    异步AsyncAppender
    数据库DBAppender
    等等。
private void filterAndLog_0_Or3Plus(final String localFQCN, final Marker marker, final Level level, final String msg, final Object[] params,final Throwable t) {final FilterReply decision = loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, msg, params, t);if (decision == FilterReply.NEUTRAL) {if (effectiveLevelInt > level.levelInt) {return;}} else if (decision == FilterReply.DENY) {return;}buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t);
}

其他日志打印格式化相关:
Appender
Encoder
Layout

开源框架日志模块

Spring && Springboot

Spring使用JCL门面,如果不引入commons-logging或其他实现jar。按上面描述会使用JDK自带JUL作为日志实现。

Springboot提供logging的starter。
spring-boot-starter-logging, 默认使用logback实现,桥接了log4j和JUL到slf4j。

TIP: 如果项目有引入commons-logging, 还需要手动引入桥接 jcl-over-slf4j

<dependencies><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version><scope>compile</scope></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-to-slf4j</artifactId><version>2.13.3</version><scope>compile</scope></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jul-to-slf4j</artifactId><version>1.7.30</version><scope>compile</scope></dependency></dependencies>

Springboot框架日志初始化流程如下:
1、监听Spring容器生命周期
在这里插入图片描述
2)LoggingSystem#get,加载具体日志系统实现,默认按如下优先级:
在这里插入图片描述
3)日志系统切入Springboot应用生命周期
监听ApplicationStartingEvent,触发LoggingSystem#beforeInitialize
监听ApplicationEnvironmentPreparedEvent,触发LoggingSystem#initialize
监听onApplicationPreparedEvent,注册日志系统相关单例bean到Spring容器
监听ContextClosedEvent/onApplicationFailedEvent, 日志系统清理

Mybatis

Mybatis对常见日志框架包装一层,使用自定义日志接口,通过配置或默认规则设置具体日志实现框架:
mybatis日志模块
1)尝试加载实现,按如下顺序优先级加载。
在这里插入图片描述

2)如果通过配置指定具体实现,则使用具体实现。

Class<? extends Log> logImpl = (Class<? extends Log>)resolveClass(props.getProperty("logImpl"));
configuration.setLogImpl(logImpl);

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

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

相关文章

面试算法-153-旋转图像

题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,…

Java项目:基于Springboot+vue实现的医院住院管理系统设计与实现(源码+数据库+开题报告+任务书+毕业论文)

一、项目简介 本项目是一套基于Springbootvue实现的医院住院管理系统设 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简…

基于Springboot+Vue实现前后端分离社团管理系统

一、&#x1f680;选题背景介绍 &#x1f4da;推荐理由&#xff1a; 21世纪时信息化的时代&#xff0c;几乎任何一个行业都离不开计算机&#xff0c;将计算机运用于社团管理也是十分常见的。过去使用手工的管理方式对大学生社团进行管理&#xff0c;造成了管理繁琐、难以维护等…

基于java+SpringBoot+Vue的房屋租赁系统设计与实现

基于javaSpringBootVue的房屋租赁系统设计与实现 开发语言: Java 数据库: MySQL技术: Spring Boot JSP工具: IDEA/Eclipse、Navicat、Maven 系统展示 前台展示 房源浏览模块&#xff1a;展示可租赁的房源信息&#xff0c;用户可以根据条件筛选房源。 预约看房模块&#…

java项目基于Springboot和Vue的高校心理教育辅导系统的设计与实现

今天要和大家聊的是基于Springboot和Vue的高校心理教育辅导系统的设计与实现 &#xff01;&#xff01;&#xff01; 有需要的小伙伴可以通过文章末尾名片咨询我哦&#xff01;&#xff01;&#xff01; &#x1f495;&#x1f495;作者&#xff1a;李同学 &#x1f495;&…

springboot实战---5.最简单最高效的后台管理系统开发

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;SpringBoot &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&…

安达发|APS软件在皮具箱包生产工艺中的应用

APS软件&#xff0c;即高级生产计划排程系统&#xff08;Advanced Planning and Scheduling&#xff09;&#xff0c;在皮具箱包生产工艺中的应用至关重要。它通过高效的生产计划和资源优化&#xff0c;帮助企业降低成本、提高生产效率和市场响应速度。以下是APS软件在皮具箱包…

day03-Docker

1.初识 Docker 1.1.什么是 Docker 1.1.1.应用部署的环境问题 大型项目组件较多&#xff0c;运行环境也较为复杂&#xff0c;部署时会碰到一些问题&#xff1a; 依赖关系复杂&#xff0c;容易出现兼容性问题开发、测试、生产环境有差异 例如一个项目中&#xff0c;部署时需要依…

代码随想录学习Day 24

93.复原IP地址 题目链接 讲解链接 本题属于切割问题&#xff0c;切割问题需要使用回溯算法来将所有的结果搜索出来&#xff0c;与前一题分割回文串是类似的。本题的树形结构如下图所示&#xff1a; 回溯三部曲&#xff1a; 1.递归函数参数及返回值&#xff1a;参数为待分割…

2012年认证杯SPSSPRO杯数学建模D题(第一阶段)人机游戏中的数学模型全过程文档及程序

2012年认证杯SPSSPRO杯数学建模 D题 人机游戏中的数学模型 原题再现&#xff1a; 计算机游戏在社会和生活中享有特殊地位。游戏设计者主要考虑易学性、趣味性和界面友好性。趣味性是本质吸引力&#xff0c;使玩游戏者百玩不厌。网络游戏一般考虑如何搭建安全可靠、丰富多彩的…

JVM高级篇之GC

文章目录 版权声明垃圾回收器的技术演进ShenandoahShenandoah GC体验Shenandoah GC循环过程 ZGCZGC简介ZGC的版本更迭ZGC体验&使用ZGC的参数设置ZGC的调优 版权声明 本博客的内容基于我个人学习黑马程序员课程的学习笔记整理而成。我特此声明&#xff0c;所有版权属于黑马…

【C++】拆分详解 - 内存管理

文章目录 前言一、C/C内存分布二、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free三、C内存管理方式  3.1 new/delete操作内置类型  3.2 new和delete操作自定义类型  3.3 operator new与operator delete函数 四、new和delete的实现原理  4.1 内置类型…

【微服务】SpringCloud之Feign远程调用

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

Solo 开发者周刊 (第10期):Sora 之后,谁是被遗忘的?谁又是被仰望的?

这里会整合 Solo 社区每周推广内容、产品模块或活动投稿&#xff0c;每周五发布。在这期周刊中&#xff0c;我们将深入探讨开源软件产品的开发旅程&#xff0c;分享来自一线独立开发者的经验和见解。本杂志开源&#xff0c;欢迎投稿。 好文推荐 Solo 社区 x 机器之心-再谈复现 …

如何利用HubSpot 出海CRM实现精准海外客户定位与拓展?

在当今全球化的商业环境中&#xff0c;企业寻求海外市场的拓展已成为增长的重要策略。然而&#xff0c;海外市场的复杂性和多样性为企业带来了巨大的挑战。为了有效地定位和拓展海外客户&#xff0c;许多企业选择了HubSpot 出海CRM作为他们的营销和销售管理工具。今天运营坛将带…

Android Glide

1.引入glide implementation com.github.bumptech.glide:glide:4.14.2 // Skip this if you dont want to use integration libraries or configure Glide. annotationProcessor com.github.bumptech.glide:compiler:4.14.2 //Glide 注解处理器 2.AndroidManifest.xml 中添加…

HarmonyOS NEXT应用开发之LocalStorage:页面级UI状态存储

LocalStorage是页面级的UI状态存储&#xff0c;通过Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。 本文仅介绍LocalStorage使用场景和相关的装饰器&#xff1a;LocalStorageProp和LocalStorageLink。 说…

购买代码签名证书时需提供哪些认证资料?

在软件开发与发布过程中&#xff0c;确保软件的可靠性和完整性至关重要&#xff0c;为此购买代码签名证书是必不可少的环节。然而&#xff0c;许多开发者对于购买该证书所需的具体材料并不十分清楚。下面就为大家详细介绍购买代码签名证书所需材料&#xff0c;助您更好地筹备和…

文心一言指令词宝典之自媒体篇

作者&#xff1a;哈哥撩编程&#xff08;视频号、抖音、公众号同名&#xff09; 新星计划全栈领域优秀创作者博客专家全国博客之星第四名超级个体COC上海社区主理人特约讲师谷歌亚马逊演讲嘉宾科技博主极星会首批签约作者 &#x1f3c6; 推荐专栏&#xff1a; &#x1f3c5;…

考研||考公||就业||其他?-------愿不再犹豫

大三下了&#xff0c;现在已经开学一个多月了&#xff0c;在上个学期的时候陆陆续续吧周围有的行动早的人已经开始准备考研了&#xff0c;当然这只是下小部分人吧&#xff0c;也有一部分人是寒假可能就开始了&#xff0c;更多的则是开学的时候&#xff0c;我的直观感受是图书馆…