SLF4J & Spring Boot日志框架

这篇具有很好参考价值的文章主要介绍了SLF4J & Spring Boot日志框架。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

JAVA日志框架

JAVA有好多优秀的日志框架,比如log4j、log4j2、logback、JUL(java.util.logging)、JCL(JAVA Common Logging)等等,logback是后起之秀,是Spring Boot默认日志框架。

今天文章的目标不是研究JAVA的这些日志框架,而是在应用中处于他们前面的日志门面SLF4J,以及初步了解一下Spring Boot的默认日志框架是在什么地方配置的、怎么替换Spring Boot默认的日志框架。

SLF4J

SFL4J,全名Simple Logging Facade for Java,意思是简单JAVA日志门面,是Facade设计模式的一个典型实现。

SFL4J本身并没有日志的任何实现,它只是一个日志门面,目的是为了让应用层能够简单的、方便的使用以上提到的各种不同的日志框架,在代码层不做任何改动的情况下,在最终部署的时候决定具体使用哪一个日志框架。冲这一点,SLF4J就非常NB,能允许程序员在编码的时候不考虑具体使用哪一个日志框架、部署的时候不需要修改一行代码、随意选择日志框架。而且,虽然不是很有必要,但是只要你高兴,应用运行的过程中你都可以随时切换日志框架,比如你刚开始选择log4j2,但是后来觉得不爽想要换成logback,只要你在开发的时候使用了SLF4J,你就可以任性地随时切换。

使用SLF4J

严格来说,SLF4J只需要一个包:slf4j-api-xxx.jar(xxx是版本号) 就可以使用,POM文件中引入:

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
    </dependency>

之后:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {

  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

应用classpath下有任何前述日志框架存在的情况下,以上代码中的日志打印语句就会根据日志框架的配置输出到控制台或者日志文件中了。

SLF4J API及jar包框架

上述案例可以发现,原则上来说,项目Pom文件引入slf4j-api之后,SLF4J就可以正常工作了,但是SLF4J可以正常工作,并不代表整个日志系统可以正常工作,因为SLF4J只是日志门面,需要绑定后端的日志框架之后,日志系统才能正常工作。

我们先看一下SLF4J官网对于SLF4J API的框架图:
SLF4J & Spring Boot日志框架,spring boot,后端,java
可以看出,如果我们采用SLF4J本家的日志框架作为我们应用的日志框架的话,比如用logback的话,我们只需要slf4j-api.jar + logback相关的jar包就可以了,或者我们用slf4j自带的simple日志框架的话,也只需要slf4j-api.jar + slf4j-simple.jar。

但是如果用其他的三方日志框架,比如log4j、或者JUL的话,由于三方框架比如log4j早在SLF4J出现之前就已经占据JAVA日志的半壁江山了,所以早期版本的日志框架不可能适应后面才出现的SLF4J,所以只能SLF4J自己想办法来适应。

SLF4J给出的解决方案就是针对各日志框架的API:


slf4j-log4j12-2.0.10.jar: 为绑定log4j version 1.2,这是一个很古老的版本了,早已宣布寿终正寝了,但是考虑到有些老系统可能还在使用log4j 1.x,所以提供了这个jar包以便兼容。其实从SLF4J 1.7.35之后,slf4j-log4j模块的调用就已经在编译器直接导航到slf4j-reload4j的调用了,所以这个模块对于新版本的SLF4J来说几乎没用了。


slf4j-reload4j-2.0.10.jar:后期版本的SLF4J绑定log4j日志框架,同时需要reload4j.jar(log4j 1.2x之后的替代品)。


slf4j-jdk14-2.0.10.jar: SLF4J绑定JUL(java14之后的内置日志框架)日志框架,同时需要JDK14。


slf4j-nop-2.0.10.jar: 应用不绑定任何日志框架的情况下的SLF4J的默认NOP实现,啥也没干,只是在应用运行进行日志框架绑定的时候不报错。


slf4j-simple-2.0.10.jar: SLF4J自己实现的一个简单的、轻量级日志框架,应该没人用。


slf4j-jcl-2.0.10.jar: 绑定Apache Commons Logging。


logback-classic-xxx.jar: logback日志框架,同时需要logback-core-xxx.jar,可直接支持SLF4J。


将以上jar包放入或移除当前应用(或者通过pom文件)后,就可以轻而易举的实现日志框架的更换,不需要你动一行代码,这就是SLF4J的魔力。

不绑定

如果不引入任何日志框架、代码中又使用了SLF4J的话,会是什么情况?

如果版本是SLF4J 1.6.0 之前的版本,没有加载任何日志框架的情况下,SLF4J在绑定日志框架的时候会抛出异常:NoClassDefFoundError 。因为绑定日志框架的时候找不到org.slf4j.impl.StaticLoggerBinder类。

之后的、SLF4J2.0之前的版本,控制台会打印:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

SLF4J2.0以上,控制台会打印:

SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.

SLF4J 1.6.0之后,如果你的项目并没有加载日志框架,SLF4J提供了一个日志哑实现,叫no-operation (NOP) logger implementation,这个NOP其实就是个假把式,所有的日志打印操作都不会得到任何输出,NOP啥都不干。

桥接API

如果你的已有应用没有使用SLF4J、而是使用JCL或log4j等JAVA日志框架,SLF4J非常贴心的为你提供了两种方案、让你能够以最小代价将as-is系统的日志框架切换到SLF4J上来:

  1. Bridging legacy APIs:桥接API
  2. slf4j-migrator:代码迁移工具

桥接API图:
SLF4J & Spring Boot日志框架,spring boot,后端,java
通过桥接API,允许你将既有系统的基于log4j、JCL、JUL等日志框架的系统迁移到SLF4J上来。原理是:jcl-over-slf4j.jar替换原有的commons-logging.jar,应用中对原来的JCL日志框架的调用接口都被替换成了jcl-over-slf4j.jar中的桥接接口,jcl-over-slf4j.jar桥接接口会将日志接口API重新定向到SLF4J中、从而纳入到SLF4J体系中来。

slf4j-migrator代码迁移工具是直接对你的代码动手术的,支持JCL、log4j、JUL的迁移:
SLF4J & Spring Boot日志框架,spring boot,后端,java

Spring Boot默认日志框架

Spring Boot的默认日志框架是在spring-boot-starter中指定的,spring-boot-starter中包含了spring-boot-starter-logging:

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
      <version>3.1.4</version>
      <scope>compile</scope>
    </dependency>

而spring-boot-starter-logging中引入了logback:

<dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.4.11</version>
      <scope>compile</scope>
    </dependency>

所以,Spring Boot的默认日志框架是logback。

如果想要替换默认的日志框架,比如换成log4j2,首先需要在pom文件中加入依赖:

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-reload4j</artifactId>
            <version>2.0.10</version>
        </dependency>

之后直接启动应用,发现:
SLF4J & Spring Boot日志框架,spring boot,后端,java
这个信息是在应用系统的早期就打印出来了,说明日志框架的加载在Spring Boot启动过程中是比较早的。

然后,logback也可以正常工作了(代码中加入log可以检查一下底层日志框架到底是啥):

    public HelloWorldController(){
        log.info("---1=2---");
        log.info(log.getClass().getName());
    }

SLF4J & Spring Boot日志框架,spring boot,后端,java
但是我们想要替换logback为log4j2的目标却没有实现!

原因在上面第一张图里已经说了,SLF4J在classpath下发现了两个provider(我们用的是SLF4J2.x版本,通过provider绑定底层日志框架)。

发现两个provider的话,SLF4J会依赖JVM随机绑定一个,我们测试的这个案例是绑定了logback。

怎么能让它绑定log4j呢?

其实通过SLF4J的源码发现了一种方法,就是指定环境变量:
SLF4J & Spring Boot日志框架,spring boot,后端,java

System property for explicitly setting the provider class. If set and the provider could be instantiated, then the service loading mechanism will be bypassed.
Since:2.0.9

如果指定了这个环境变量,SLF4J的加载机制就会被跳过而直接加载指定的provider,比如:
SLF4J & Spring Boot日志框架,spring boot,后端,java
从代码看这个设置也是应该能生效的:

static List<SLF4JServiceProvider> findServiceProviders() {
        List<SLF4JServiceProvider> providerList = new ArrayList<>();

        // retain behaviour similar to that of 1.7 series and earlier. More specifically, use the class loader that
        // loaded the present class to search for services
        final ClassLoader classLoaderOfLoggerFactory = LoggerFactory.class.getClassLoader();

        SLF4JServiceProvider explicitProvider = loadExplicitlySpecified(classLoaderOfLoggerFactory);
        if(explicitProvider != null) {
            providerList.add(explicitProvider);
            return providerList;
        }

loadExplicitlySpecified方法:

static SLF4JServiceProvider loadExplicitlySpecified(ClassLoader classLoader) {
        String explicitlySpecified = System.getProperty(PROVIDER_PROPERTY_KEY);
        if (null == explicitlySpecified || explicitlySpecified.isEmpty()) {
            return null;
        }
        try {
            String message = String.format("Attempting to load provider \"%s\" specified via \"%s\" system property", explicitlySpecified, PROVIDER_PROPERTY_KEY);
            Util.report(message);
            Class<?> clazz = classLoader.loadClass(explicitlySpecified);
            Constructor<?> constructor = clazz.getConstructor();
            Object provider = constructor.newInstance();
            return (SLF4JServiceProvider) provider;
        } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            String message = String.format("Failed to instantiate the specified SLF4JServiceProvider (%s)", explicitlySpecified);
            Util.report(message, e);
            return null;
        } catch (ClassCastException e) {
            String message = String.format("Specified SLF4JServiceProvider (%s) does not implement SLF4JServiceProvider interface", explicitlySpecified);
            Util.report(message, e);
            return null;
        }
    }

如果指定了这个系统参数的话,就直接通过classloader实例化这个provider…但是确实没有测试成功,暂时没找到原因。

我们还有另外一个启用log4j2、停用logback的方案,pom文件排除logback:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

之后刷新pom,发现logback的引用已经消失了。
刷新前:
SLF4J & Spring Boot日志框架,spring boot,后端,java
刷新后:
SLF4J & Spring Boot日志框架,spring boot,后端,java

启动应用:
SLF4J & Spring Boot日志框架,spring boot,后端,java
就会发现Spring Boot项目使用log4j就没有用logback那么舒服了,log4j是需要配置的。随便放一个log4j.properties配置文件就可以正常工作了。

@Slf4j注解

@Slf4j是lombok的一个注解,所以你就能知道他其实没啥,语法糖而已,帮着你在当前类生成一个:

private static final org.slf4j.Logger log =org.slf4j.LoggerFactory.getLogger(Youclass.class);

Ohhh…OK文章来源地址https://www.toymoban.com/news/detail-795773.html

到了这里,关于SLF4J & Spring Boot日志框架的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • SLF4J门面日志框架源码探索

    SLF4J即Simple Logging Facade for Java,它提供了Java中所有日志框架的简单外观或抽象。因此,它使用户能够使用单个依赖项处理任何日志框架,例如:Log4j,Logback和JUL(java.util.logging)。通过在类路径中插入适当的 jar 文件(绑定),可以在部署时插入所需的日志框架。如果要更换日志

    2024年02月09日
    浏览(63)
  • SLF4J日志框架在项目中使用

    SLF4J全称“Simple Logging Facade for Java”,作为各种日志框架的简单门面。例如: java.util.logging、logback 、 reload4j等。只需要切换日志框架的jar包依赖就可以切换日志框架。 SLF4J支持的日志框架包含如下: log4j:常用的日志框架,需要有配置文件log4j.properties logback:可以通过logba

    2024年02月02日
    浏览(41)
  • SLF4J门面日志框架源码探索 | 京东云技术团队

    SLF4J即Simple Logging Facade for Java,它提供了Java中所有日志框架的简单外观或抽象。因此,它使用户能够使用单个依赖项处理任何日志框架,例如:Log4j,Logback和JUL(java.util.logging)。通过在类路径中插入适当的 jar 文件(绑定),可以在部署时插入所需的日志框架。如果要更换日志

    2024年02月11日
    浏览(44)
  • 微服务学习系列15:日志框架slf4j使用和原理

    目录   前言 一、slf4j 项目Github地址: slfj4j桥接API slf4j 项目模块描述 二、slf4j-api 简单使用 代码分析  三、基础知识 外观模式 适配器模式 什么是桥接模式 什么是SPI 什么是API 四、设计分析 参考 slf4j主要是为了给Java日志访问提供一个标准、规范的API框架,其主要意义在于提

    2024年02月07日
    浏览(37)
  • 【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)
  • 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)
  • 日志框架梳理(Log4j,Reload4j,JUL,JCL,SLF4J,Logback,Log4j2)

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

    2024年02月05日
    浏览(55)
  • 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日志并输出到文件中

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

    2024年02月06日
    浏览(44)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包