首页 > 其他分享 >从门面模式到 SLF4J 及其 getLogger 方法原理

从门面模式到 SLF4J 及其 getLogger 方法原理

时间:2024-10-25 23:21:47浏览次数:6  
标签:调用 StaticLoggerBinder 实现 getLogger SLF4J 门面 日志

基于以下内容总结:从门面模式到 Slf4j10 分钟讲清楚 Java SLF4J,Java 日志框架的扛把子,从原理到实践

写后端接口的时候,先写一个 Service 接口,这个 Service 接口的实现中可能会调用多个其他 Service 或 Mapper 方法来实现某个业务,对于 Controller,只需要传递参数给 Service 方法就好了,这时供 Controller 调用的 Service 就是一个门面。

门面模式的主要目的是给外界提供更简单的接口。要完成一个任务,往往需要多个子系统协作,不使用门面时,客户端需要调用各子系统的多个方法,操作繁琐容易出错,使用门面时,客户端调用门面的简单接口,不用考虑太多细节,子系统交给门面调用。

门面(外观)模式也能起到统一接口的作用,当有一组完成类似功能的接口时,门面对外暴露一个统一的外形,调用方不需要知道它外形之下的具体实现是什么。很像 Java Interface 提供的作用了,但这里可能粒度更大一些,门面后面往往是一些大粒度的子系统。

简介

试想,原先我需要自己调用多个子系统各自部分或全部的功能接口以完成我的需求:

2018-08-30-15356106508820

而使用门面模式重构后,只需要调用门面提供的统一功能入口即可:

2018-08-30-15356107001587

日志框架中的应用

日志系统应该是最常见的门面模式的应用了,我们以 SLF4J 门面框架为例。

SLF4J(Simple Logging Facade for Java)和 JCL(Jakarta Commons Logging)是两个不同的日志门面系统。

介绍

SLF4J 提供了日志接口,方便程序获取具体日志对象,其自带的简单日志记录实现 slf4j-simple、自带的空实现 slf4j-nop、日志框架 Logback 等,均直接实现了 SLF4J。第三方日志框架如 reload4j、JDK 内置的日志实现 JUL 等并不直接实现 SLF4J,而是由 SLF4J 提供的适配层 slf4j-reload4j、slf4j-jdk14 来实现向 SLF4J 的适配转换。参见下图,图片来自 SLF4J 官网

2018-08-30-concrete-bindings
翻译
2018-08-30-concrete-bindings

下面是 SLF4J 与各种底层日志框架的依赖关系:

2018-08-30-concrete-bindings

使用

获取日志对象:

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

记录日志:

logger.debug("message is {}.", message);

这里会引出一个问题,也就是LoggerFactory.getLogger(SomeService.class)是如何获取到具体的实现层实例的。

绑定实际使用的子系统

类加载机制

在 1.7 版本之前,基于类加载机制实现和实现层的绑定。

类加载时,getLogger()尝试获取 Logger 实例:

image-20200606161315662

getILoggerFactory()实例化 StaticLoggerBinder 单例,后者在不同日志框架中有不同实现:

image-20200606162010335

performInitialization()调用bind()绑定日志框架实现:

image-20200606161405254

findPossibleStaticLoggerBinderPathSet尝试在类路径中加载org/slf4j/impl/StaticLoggerBinder.class

image-20200606161405254

如果发现有多个StaticLoggerBinder.class,说明类路径下存在多个日志实现层,reportMultipleBindingAmbiguity方法会给出错误提示(但不会报错)。

image-20200606161405254

StaticLoggerBinder.getSingleton()真正完成和实现层的绑定,虚拟机将尝试加载StaticLoggerBinder这个类。没找到则会报NoClassDefFoundError异常,并被 SLF4J 捕获给出错误消息(并不会报错,SLF4J 会和自带的 NOP 实现绑定):

无任何实现
无任何实现

NOP 即 no operation,也就是不打印任何日志。

如果找到多个则 SLF4J 也不知道最终会使用哪个,只是会给出日志信息:

image-20200606162417530

所以一定要注意排查是否有多个当前日志门面的实现,若有,那么系统整体的日志打印将不可控(不论是性能还是日志位置)。

Log4j2 中的 StaticLoggerBinder:

image-20200606161601087

另:如果下载 SLF4J 的源码,会发现 StaticLoggerBinder 这个类是找不到的。这是因为在编写 SLF4J 框架时,为保证编译通过,会提供一个空实现,而在打包发布的时候,会将其移除,这样虚拟机加载到的才是具体的日志实现层:

image-20200606161601087

SPI 机制

使用类加载机制实现绑定有一些问题:

  • 对于其他框架来说,要实现一个包名为org.slf4j.impl的类;
  • 对于 SLF4J 本身来说,其 jar 包中不能有 StaticLoggerBinder 这个类,打包时需要删除。

所以后面就改为通过 SPI 机制实现了。

img
img
img

performInitialization()调用bind()方法:

img

findServiceProviders()中调用的getServiceLoader()方法:

img

getServiceLoader()方法中调用ServiceLoader.load()方法完成对SLF4JServiceProvider实现类的加载:

img

标签:调用,StaticLoggerBinder,实现,getLogger,SLF4J,门面,日志
From: https://www.cnblogs.com/Higurashi-kagome/p/18503228

相关文章

  • 设计模式——门面模式 | 外观模式
    哈喽,各位盆友们!我是你们亲爱的学徒小z,今天给大家分享的文章是设计模式的——门面模式。文章目录定义通用类图1.通用结构2.优点3.缺点使用场景注意事项1.一个子系统可以有多个门面2.门面不参与子系统内的业务逻辑定义定义:要求一个子系统的外部与其内部的通信必须......
  • 【idea】log4j和slf4j配合使用问题(2024-9-23最新版本)!
    1、slf4j<!--https://mvnrepository.com/artifact/org.slf4j/slf4j-simple--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version......
  • 设计模式---- 门面模式
    门面模式门面模式(FacadePattern)是一种结构型设计模式,用于为复杂子系统提供一个统一、简单的接口,隐藏系统的复杂性。通过门面模式,客户端无需直接与系统的内部组件交互,而是通过门面类与系统打交道,简化了客户端的使用,降低了系统的复杂性和耦合度。门面模式的主要概念定义:门面模......
  • 一起学Java(12)-[日志篇]教你分析SLF4J源码,掌握SLF4J如何与Logback无缝集成的原理
    继续完成上篇(一起学Java(11)-[日志篇]教你分析SLF4J源码,掌握Logger接口实现类加载原理)留给自己的任务,研究Logback是如何和 SLF4J无缝集成的。在之前的SLF4J源码研究中(教你分析SLF4J源码,掌握Logger接口实现类加载原理)我们已经知道SLF4J中利用java.util.ServiceLoader 机......
  • Java日志框架:Log4j2与SLF4J的比较与选择
    Java日志框架:Log4j2与SLF4J的比较与选择大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!日志记录是Java应用程序中一个重要的功能,它帮助开发者监控应用的运行状态和调试问题。Log4j2和SLF4J是Java中两个广泛使用的日志框架,它们各有特点和优势。本文将......
  • 一起学Java(11)-[日志篇]教你分析SLF4J源码,掌握Logger接口实现类加载原理
    最近各种事情很忙,今天继续。在第十篇(一起学Java(10)-为项目引入Log框架(Log篇二-引入SLF4J接口层框架))中,我们为项目(https://github.com/lihongzheshuai/java-all-in-one)引入了SLF4J和Logback框架,按计划通过阅读源码研究下SLF4J的实现原理。全文详见个人独立博客:https://ww......
  • SpringBoot整合日志功能(slf4j+logback)详解
     目录一、日志门面与日志实现1.1什么是日志门面和日志实现?1.2为什么需要日志门面?二、简介三、日志格式四、记录日志4.1使用日志工厂4.2 使用Lombok的@Slf4j注解五、日志级别5.1日志级别介绍5.2配置日志级别5.3指定某个包下的类使用某个级别5.4占位符打......
  • SLF4J: Class path contains multiple SLF4J bindings. 运行报错 表示在您的应用程序
    java使用SLF4J时出现下面的错误,是因为项目中使用了多个SLF4J的类库SLF4J:ClasspathcontainsmultipleSLF4Jbindings.SLF4J:Foundbindingin[jar:file:/D:/%e5%bd%93%e5%89%8d%e5%b7%a5%e4%bd%9c/SipPBX%e8%ae%af%e6%97%b6/JoinCallOMCC/JoinCallOMCC/out/artifacts/......
  • Java中的日志管理:SLF4J与Logback
    Java中的日志管理:SLF4J与Logback大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!本文将介绍如何在Java中使用SLF4J与Logback进行日志管理,帮助您在项目中实现高效的日志记录和管理。一、SLF4J与Logback简介SLF4J(SimpleLoggingFacadeforJava)是一种简单......
  • hbase SLF4J报错
    hbaseSLF4J报错HBaseSLF4J错误的解决方法介绍在使用HBase开发过程中,经常会遇到SLF4J报错的情况。SLF4J(SimpleLoggingFacadeforJava)是一个为Java应用程序提供日志记录接口的简单日志门面。本文将介绍如何解决HBase中常见的SLF4J报错问题。解决流程下面是解决HBaseSLF4......