微服务学习系列15:日志框架slf4j使用和原理

这篇具有很好参考价值的文章主要介绍了微服务学习系列15:日志框架slf4j使用和原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 

目录

 

前言

一、slf4j

项目Github地址:

slfj4j桥接API

slf4j 项目模块描述

二、slf4j-api

简单使用

代码分析 

三、基础知识

外观模式

适配器模式

什么是桥接模式

什么是SPI

什么是API

四、设计分析

参考



前言

slf4j主要是为了给Java日志访问提供一个标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如log4j和logback等。对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。


一、slf4j

官网地址:https://www.slf4j.org/manual.html

项目Github地址:

https://github.com/qos-ch/slf4j

slfj4j桥接API

slf4j,log4j,架构,java

slf4j 项目模块描述

模块 描述
slf4j-api 日志的统一接口
slf4j-jdk14 jul到SLF4J的绑定,将强制SLF4J的调用分配给jul
slf4j-log4j12 log4j 到SLF4J的绑定,将强制SLF4J的调用分配给 log4j
jcl-over-slf4j 将commons-logging框架的日志桥接到slf4j上来
log4j-over-slf4j 将 log4j 框架的日志桥接到slf4j上来

二、slf4j-api

简单使用

slf4j-api是slf4j的api模块,提供了日志输出的API,值得一提的是从slf4j 1.8起,slf4j使用SPI的方式寻找日志实现框架,而在此之前则是通过寻找指定类的方式发现并绑定实现框架。先通过一个简单的入门案例来分析它的实现方式。

public class TestLog {
    private static final Logger logger = LoggerFactory.getLogger(TestLog.class);

    public static void main(String[] args) {
        logger.info("hello world");
    }
}

20:56:33.344 [main] INFO com.test.TestLog - hello world 

代码分析 

先来分析 LoggerFactory.getLogger(TestLog.class) 这行代码,LoggerFactory.getLogger() 返回一个 Logger 对象,我们看看LoggerFactory 类的实现

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

    public static Logger getLogger(Class<?> clazz) {
        Logger logger = getLogger(clazz.getName());
        if (DETECT_LOGGER_NAME_MISMATCH) {
            Class<?> autoComputedCallingClass = Util.getCallingClass();
            if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
                Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(), autoComputedCallingClass.getName()));
                Util.report("See https://www.slf4j.org/codes.html#loggerNameMismatch for an explanation");
            }
        }

        return logger;
    }
}

重点关注 getILoggerFactory 方法 ,它返回一个日志工厂类。ILoggerFactory 是一个slf4j 提供的一个接口,可以猜测 到 getILoggerFactory方法应该是拿到了其实现类.

    public static ILoggerFactory getILoggerFactory() {
        return getProvider().getLoggerFactory();
    }

getProvider() 方法返回SLF4JServiceProvider,其中SLF4JServiceProvider同样是slf4j-api中提供的一个接口,那么getProvider肯定是通过某种方法拿到了该接口的实现类。

 static SLF4JServiceProvider getProvider() {
        if (INITIALIZATION_STATE == 0) {
            Class var0 = LoggerFactory.class;
            synchronized(LoggerFactory.class) {
                if (INITIALIZATION_STATE == 0) {
                    INITIALIZATION_STATE = 1;
                    performInitialization();
                }
            }
        }

        switch (INITIALIZATION_STATE) {
            case 1:
                return SUBST_PROVIDER;
            case 2:
                throw new IllegalStateException("org.slf4j.LoggerFactory in failed state. Original exception was thrown EARLIER. See also https://www.slf4j.org/codes.html#unsuccessfulInit");
            case 3:
                return PROVIDER;
            case 4:
                return NOP_FALLBACK_SERVICE_PROVIDER;
            default:
                throw new IllegalStateException("Unreachable code");
        }
    }
 重点关注 performInitialization 方法
  private static final void performInitialization() {
        bind();
        if (INITIALIZATION_STATE == 3) {
            versionSanityCheck();
        }
    }

   bind 方法

 private static final void bind() {
       List<SLF4JServiceProvider> providersList = findServiceProviders();
    }

 从 findServiceProviders 方法中 可以 知道 是通过SPI的方式寻找SLF4JServiceProvider的实现类.

    private static List<SLF4JServiceProvider> findServiceProviders() {
        ServiceLoader<SLF4JServiceProvider> serviceLoader = ServiceLoader.load(SLF4JServiceProvider.class);
        List<SLF4JServiceProvider> providerList = new ArrayList();
        Iterator var2 = serviceLoader.iterator();

        while(var2.hasNext()) {
            SLF4JServiceProvider provider = (SLF4JServiceProvider)var2.next();
            providerList.add(provider);
        }

        return providerList;
    }

三、基础知识

外观模式

外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。

这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。

适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。

什么是桥接模式

桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。

什么是SPI

SPI全名Service Provider interface,翻译过来就是“服务提供接口”,再说简单就是提供某一个服务的接口, 提供给服务开发者或者服务生产商来进行实现。
Java SPI 是JDK内置的一种动态加载扩展点的实现。
这个机制在一般的业务代码中很少用到(个人接触到的业务没有用到过),但是再底层框架中却被大量使用,包括JDBC、Dubbo、Spring框架、日志接口中都有用到,不同的是有的使用Java原生的实现,有的框架则自己实现了一套SPI机制

slf4j,log4j,架构,java

当接口是由服务调用方提供,并且由服务提供方进行实现时,服务调用方就可以根据自己的需要选择特定实现,而不用更改业务代码以获取相应的功能,这个就是SPI

什么是API

API 全称Application Programming Interface, 翻译为“应用程序接口”,指的是应用程序为外部提供服务的接口,这个接口通常由服务提供者自行开发,定义好接口后很少改动。

slf4j,log4j,架构,java

一般应用(模块)之间通过接口进行通讯,服务提供方提供接口并进行实现后,调用方就可以通过调用这个接口拥有服务提供方提供的能力,这个就是API

API 中的接口是服务提供者给服务调用者的一个功能列表,而 SPI 中更多强调的是,服务调用者对服务实现的一种约束,服务提供者根据这种约束实现的服务,可以被服务调用者发现。 

四、设计分析

了解了slf4j  的简单使用后,我们来看看它是设计的核心接口类

public interface Logger {}
public interface ILoggerFactory {

    public Logger getLogger(String name);
}
public interface SLF4JServiceProvider {

    /**
     * Return the instance of {@link ILoggerFactory} that 
     * {@link org.slf4j.LoggerFactory} class should bind to.
     * 
     * @return instance of {@link ILoggerFactory} 
     */
    public ILoggerFactory getLoggerFactory();


    /**
     * Initialize the logging back-end.
     * 
     * <p><b>WARNING:</b> This method is intended to be called once by 
     * {@link LoggerFactory} class and from nowhere else. 
     * 
     */
    public void initialize();
}

slf4j,log4j,架构,java

      我们看看Log4j 的桥接方式

Reload4jServiceProvider 实现 SLF4JServiceProvider

public class Reload4jServiceProvider implements SLF4JServiceProvider {
    public static String REQUESTED_API_VERSION = "2.0.99"; // !final

    private ILoggerFactory loggerFactory;
    private IMarkerFactory markerFactory;
    private MDCAdapter mdcAdapter;

    public Reload4jServiceProvider() {
        try {
            @SuppressWarnings("unused")
            Level level = Level.TRACE;
        } catch (NoSuchFieldError nsfe) {
            Util.report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
        }
    }

    @Override
    public void initialize() {
        loggerFactory = new Reload4jLoggerFactory();
        markerFactory = new BasicMarkerFactory();
        mdcAdapter = new Reload4jMDCAdapter();
    }

    @Override
    public ILoggerFactory getLoggerFactory() {
        return loggerFactory;
    }
}

 slf4j,log4j,架构,java

在 resources/META-INF/services 路径下 创建文件org.slf4j.spi.SLF4JServiceProvider 。文件名为 slf4j中SLF4JServiceProvider 的全路径名,在文件 org.slf4j.spi.SLF4JServiceProvider 中存放实现类

org.slf4j.reload4j.Reload4jServiceProvider

系统启动会自动扫描 resources/META-INF/services 下的文件,调用实现类的构造方法,完成对象的初始化。从Reload4jServiceProvider 中 可以获取到ILoggerFactory 的 实现类了。

参考

JavaSPI详解_Java程序V的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-730295.html

到了这里,关于微服务学习系列15:日志框架slf4j使用和原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【SpringBoot中使用SLE4J日志框架启动报错:SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinde】

    1.1 出现的问题 SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”. SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. 1.2 原因分析 检查自己的maven依赖,发现已经引入了slf4j-api了,这是为什么呢?其原因是,SLF4J本身

    2024年02月13日
    浏览(37)
  • 如何在 Spring Boot 中集成日志框架 SLF4J、Log4j

    笔者的操作环境: Spring Cloud Alibaba:2022.0.0.0-RC2 Spring Cloud:2022.0.0 Spring Boot:3.0.2 Nacos 2.2.3 Maven 3.8.3 JDK 17.0.7 IntelliJ IDEA 2022.3.1 (Ultimate Edition) 因为 Spring Boot 已经内置了 Logback,所以需要先将 Logback 移除。移除的方法是在 Spring Boot 依赖包中移除 Logback。 比如就像这样: 【踩坑提

    2024年02月13日
    浏览(44)
  • 学习SpringBoot使用slf4j日志并输出到文件中

    再使用前,先了解一下介绍,否则你也不会用! 1、日志级别 SLF4J将日志分为trace、debug、info、warn、error五个级别,每个级别对应记录不同的日志,对应不同的使用场景。 日志级别从低到高分为 TRACE DEBUG INFO WARN ERROR FATAL 如果设置为 WARN ,则低于 WARN 的信息都不会输出 一般设

    2024年02月06日
    浏览(43)
  • SpringBoot集成slf4j日志系统

    作者平台: | CSDN:blog.csdn.net/qq_4115394… | 掘金:juejin.cn/user/651387… | 知乎:www.zhihu.com/people/1024… | GitHub:github.com/JiangXia-10… | 微信公众号:1024笔记 本文大约4777字,预计阅读时长11分钟 日志系统作为一个应用系统的重要部分之一,它能够有助于我们在系统在线上环境中如果

    2023年04月19日
    浏览(41)
  • Spring Boot 日志配置(Slf4j)

    SLF4J与Logback简介 Java日志框架众多,常用的有java.util.logging, log4j, logback,commons-logging等。 SLF4J (Simple Logging Facade For Java),它是一个针对于各类Java日志框架的统一Facade抽象。SLF4J定义了统一的日志抽象接口,而真正的日志实现则是在运行时决定。 LogBack是由log4j的创始人开发的新

    2024年02月16日
    浏览(51)
  • 日志框架梳理(Log4j,Reload4j,JUL,JCL,SLF4J,Logback,Log4j2)

    文中代码示例获取:关注【 Qin的学习营地 】,回复【 日志框架梳理 】 在了解日志框架时总会列出一系列框架:Log4j,Reload4j,JUL,JCL,SLF4J,Logback,Log4j2,这么多框架让人感到混乱,该怎么选取、该怎么用。接下来,让我们逐步理清这些框架及之间的关系。 首先来了解日志

    2024年02月05日
    浏览(55)
  • Spring Boot日志:SLF4J和Logback

    SpringBoot中的日志库分为两种: 实现库:提供具体的日志实现,例如日志级别的控制、打印格式、输出目标等。 外观库:自身不提供日志实现,而是对其他日志库进行封装,从而方便使用。基于外观模式实现。 关于外观库的出现,可设想一下:现在有多种日志库,每一种接口

    2024年02月15日
    浏览(50)
  • 6.2 SpringBoot日志入门实战 SLF4J + Logback

    如果你是一位Java开发者,那么你肯定知道Log日志的重要性,它是我们了解程序内部运行真像,分析和定位问题的最直接手段!对于任何企业级的程序,日志记录是必须的! 在SpringBoot框架中,集成了常用的日志框架,包括SLF4J、Logback、Log4j2、Java Util Logging等,其中,Logback是

    2024年02月08日
    浏览(41)
  • 【JavaEE进阶】 关于⽇志框架(SLF4J)

    SLF4J不同于其他⽇志框架,它不是⼀个真正的⽇志实现,⽽是⼀个抽象层,对⽇志框架制定的⼀种规范、标准、接⼝.所有SLF4J并不能独⽴使⽤,需要和具体的⽇志框架配合使⽤ SLF4J是⻔⾯模式的典型应⽤(但不仅仅使⽤了⻔⾯模式). ⻔⾯模式(Facade Pattern)⼜称为外观模式,提供了⼀个

    2024年01月22日
    浏览(46)
  • SpringBoot集成slf4j日志和logback.xml配置详解

    slf4j,即(Simple Logging Facade for Java,简单门面日志)。它是对所有日志框架制定的一种 规范、标准、接口 ,并不是一个框架的具体的实现,它只服务于各种各样的日志系统。 slf4j提供了统一的记录日志的接口,对不同日志系统的具体实现进行了抽象化,只要按照其提供的方法记

    2024年02月03日
    浏览(72)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包