slf4j是如何绑定具体的日志框架的?

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: slf4j是如何绑定具体的日志框架的?

阅读分析slf4j的日志源码,发现其中涵盖了许多知识点和优秀的设计,关键它们都是活生生的实践案例。写成系列文章与大家分享,欢迎持续关注。第3篇。

slf4j日志框架绑定流程

在《slf4j中是如何运用SPI机制兼容各种日志框架的》一文当中,我们讲到slf4j通过SPI机制,可以扫描到对应日志框架jar包中META-INF/services下配置的SLF4JServiceProvider的实现类。进而通过SLF4JServiceProvider的实现类获得对应Logger的工厂类。

关于相关SPI的更多内容,可以回头看上篇文章。本篇文章开始,我们首先想一个问题,如果项目中出现多个日志框架,也就出现多个SLF4JServiceProvider的SPI相关配置,针对这种情况slf4j会如何处理?我们在使用的过程中又该注意些什么?

LoggerFactory的bind方法

要解决上面的问题,先来看一下LoggerFactory中绑定SLF4JServiceProvider的bind方法的具体实现代码:
































private static void bind() {    try {        List<SLF4JServiceProvider> providersList = findServiceProviders();        // 如果出现多个SLF4JServiceProvider实例,则打印警告信息。        reportMultipleBindingAmbiguity(providersList);        // 判断是否扫描到对应的SLF4JServiceProvider实现类        if(!providersList.isEmpty()) {            PROVIDER = providersList.get(0);            // SLF4JServiceProvider.initialize() is intended to be called here and nowhere else.            PROVIDER.initialize();            INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;            // 打印绑定了哪个SLF4JServiceProvider            reportActualBinding(providersList);        } else {            // 如果未扫描到对应的实现类,初始化状态变为无操作的应急NOPServiceProvider            INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;            // 下面三行警告信息,在项目中未使用日志框架时,经常会看到。            Util.report("No SLF4J providers were found.");            Util.report("Defaulting to no-operation (NOP) logger implementation");            Util.report("See " + NO_PROVIDERS_URL + " for further details.");
            // 打印忽略掉的静态Logger绑定            Set<URL> staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();            reportIgnoredStaticLoggerBinders(staticLoggerBinderPathSet);        }        postBindCleanUp();    } catch (Exception e) {        failedBinding(e);        throw new IllegalStateException("Unexpected initialization failure", e);    }}

通过bind方法源码,我们可以看出绑定SLF4JServiceProvider(也就是对应的日志框架实现该接口的实例)的流程为:

  • 1、通过SPI机制扫描项目类路径下所有实现SLF4JServiceProvider接口并按照SPI机制配置的类;
  • 2、如果出现多个SLF4JServiceProvider实例,会打印警告信息;
  • 3、如果实例列表中存在1个或多个实例,只获取第一个实例。此处需要注意,如果配置多个日志框架,只会使用最先被加载的那一个;
  • 4、如果一个日志框架都不存在,则打印警告信息。

上述流程中我们需要注意什么?

第一,尽量避免在使用slf4j的时候出现多个日志框架,即便其他日志框架因三方框架引入,我们也可以通过调整SLF4JServiceProvider的引入来避免。比如当我们引入了logback框架时,对应的SPI配置位于logback-classic-xx.jar中,而logback-core-xx.jar中并没有,也就是如果不引入logback-classic的jar包,就不会触发SPI机制。同样的,如果想使用slf4j来集成log4j,那仅仅引入log4j的日志框架是无效的,还需要引入slf4j为其配置的SPI的依赖slf4j-log4j12,slf4j才能够扫描的到。

第二,如果启动程序时,看到控制台打印如下警告信息,你应该知道slf4j并没有成功扫描到日志框架。




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

上面的警告信息在我们使用了slf4j,但并未引入其他日志框架,或没有引入桥接的依赖时经常会出现。通过阅读上面的源代码,我们很明确的知道该异常信息为什么会发生,如何去解决了。

第三,如果扫描到多个日志框架,怎么确定当前使用了哪个?可通过上述代码中reportActualBinding打印的日志来判断:"Actual provider is of type [" + providerList.get(0) + "]"。此时如果并不是项目需要使用的日志框架,可参考第一条,在pom文件中进行排查依赖处理。

找到多个实现类会取第一个,但是谁是第一个呢?看官方解释:

The warning emitted by SLF4J is just that, a warning. Even when multiple bindings are present, SLF4J will pick one logging framework/implementation and bind with it. The way SLF4J picks a binding is determined by the JVM and for all practical purposes should be considered random. As of version 1.6.6, SLF4J will name the framework/implementation class it is actually bound to.

答案就是:取决于JVM,你可以认为就是随机的。

小结

我们经常在使用日志框架,也经常在使用slf4j,我们还经常看到一些SLF4J的警告信息,只有像本篇文章这样,认证阅读了相应的源码,了解了底层处理的业务逻辑,我们才能够更好的知道什么情况下该做怎样的处理,什么异常是什么原因导致的。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
12天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
118 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
1月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
218 3
|
22天前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
86 1
|
1月前
|
数据采集 监控 Java
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
本文是关于SpringBoot日志的详细教程,涵盖日志的定义、用途、SLF4J框架的使用、日志级别、持久化、文件分割及格式配置等内容。
129 0
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
|
2月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
45 2
|
1月前
|
SQL XML 监控
SpringBoot框架日志详解
本文详细介绍了日志系统的重要性及其在不同环境下的配置方法。日志用于记录系统运行时的问题,确保服务的可靠性。文章解释了各种日志级别(如 info、warn、error 等)的作用,并介绍了常用的日志框架如 SLF4J 和 Logback。此外,还说明了如何在 SpringBoot 中配置日志输出路径及日志级别,包括控制台输出与文件输出的具体设置方法。通过这些配置,开发者能够更好地管理和调试应用程序。
|
2月前
|
Java
日志框架log4j打印异常堆栈信息携带traceId,方便接口异常排查
日常项目运行日志,异常栈打印是不带traceId,导致排查问题查找异常栈很麻烦。
|
2月前
|
运维 NoSQL Java
SpringBoot接入轻量级分布式日志框架GrayLog技术分享
在当今的软件开发环境中,日志管理扮演着至关重要的角色,尤其是在微服务架构下,分布式日志的统一收集、分析和展示成为了开发者和运维人员必须面对的问题。GrayLog作为一个轻量级的分布式日志框架,以其简洁、高效和易部署的特性,逐渐受到广大开发者的青睐。本文将详细介绍如何在SpringBoot项目中接入GrayLog,以实现日志的集中管理和分析。
229 1
|
3月前
|
存储 监控 Java
Java日志通关(三) - Slf4j 介绍
作者日常在与其他同学合作时,经常发现不合理的日志配置以及五花八门的日志记录方式,后续作者打算在团队内做一次Java日志的分享,本文是整理出的系列文章第三篇。
|
3月前
|
人工智能 Java Spring
Spring框架下,如何让你的日志管理像‘AI’一样智能,提升开发效率的秘密武器!
【8月更文挑战第31天】日志管理在软件开发中至关重要,不仅能帮助开发者追踪问题和调试程序,还是系统监控和运维的重要工具。在Spring框架下,通过合理配置Logback等日志框架,可大幅提升日志管理效率。本文将介绍如何引入日志框架、配置日志级别、在代码中使用Logger,以及利用ELK等工具进行日志聚合和分析,帮助你构建高效、可靠的日志管理系统,为开发和运维提供支持。
64 0