Slf4j与其他日志系统兼容的使用

java生产的各种框架(如spring等)里各个框架会使用不同的日志体系,多个不同日志在一个jvm里混搭会出现一定问题 ,这里梳理一下java体系里常见的日志框架,以SFL4j为中心介绍下跟各个日志框架的关系,介绍下生产环境如何打理各种日志框架。

1. 接口简介

在java的体系里,主要有slf4j和common-logging两种日志体系接口。实现的框架有很多,主流的诸如logback、log4j等。

当然,虽然都是接口,但两者也可以通过桥接包实现相互的日志代理输出。

common-logging挂载的日志实现常为log4j。在初始化的时候,如果没有特殊指定要挂载谁,会自动按上图顺序去实例化实现,log4jLogger封装了log4j的logger,打印日志的时候调用到log4j过去。

2. SLF4j 的桥接和被桥接

slf4j作为一个接口定义,底层可以有很多实现框架,同时也可以支持别的日志实现或者框架打到sfl4j上。它的实现是基于不同的桥接包。

2.1 slf4j的桥接

slf4j作为接口定义,下面有很多种实现。实现原理是获取ILoggerFactory时执行初始化,初始化过程绑定实现对象:load出所有实现StaticLoggerBinder的类,然后获取他的单例,后面执行getLogger的时候都是调用这个单例类的方法获取对应有具体实现日志功能的Logger对象。如果有多个实现,之后绑定其中的一个。这种情况需要排除掉不需要的日志实现类。

2.2 slf4j的被桥接

上图展示了其他日志系统如何接入到slf4j日志体系,其中基本原理是针对各自日志体系做了代理 ,输出到了sfl4j接口中,具体实现可以去看桥接包的实现。基本都是对原日志体现做了重新实现,然后底层实际调用日志输出的方法是走到了slf4j上面 。

只有jul是个例外,因为是java自带jdk实现,没法去重新那些类,这个地方根据jul的handler扩展机制实现了一个slf4j的handler然后把日志写到slf4j上面。同时要生效的话,还要修改jre/lib/logging.properties把新的handler配置到.handlers属性中。一般生产不会去这么搞。

2.3 应用

实际项目应用的时候要注意,桥接和被桥接的包不能同时出现,不然会出现死循环了,比如sfl4j既桥接了log4j又被log4j桥接,那log4j输出调用会指向slf4j,slf4j又指向log4j如此循环。一定要注意排除掉无用的包。

生产建议:slf4j-api下挂载的实现只保留logback,上层的日志打印桥接可以存在都指向到slf4j。

参考如下依赖,其他关于log的包统统排掉:

<dependencies>    <dependency>        <groupId>org.slf4j</groupId>        <artifactId>slf4j-api</artifactId>        <version>1.7.24</version>    </dependency>    <dependency>        <groupId>ch.qos.logback</groupId>        <artifactId>logback-classic</artifactId>        <version>1.2.1</version>    </dependency>

<dependency>        <groupId>org.slf4j</groupId>        <artifactId>jcl-over-slf4j</artifactId>        <version>1.7.14</version>    </dependency>    <dependency>        <groupId>org.slf4j</groupId>        <artifactId>log4j-over-slf4j</artifactId>        <version>1.7.24</version>    </dependency>

<dependency>        <groupId>org.slf4j</groupId>        <artifactId>jul-to-slf4j</artifactId>        <version>1.7.7</version>    </dependency></dependencies>

  

3. 测试代码实现及pom

测试代码

public class TestLoggers {

    /**
     * slf4j-api -->slf4j-log4j12 -> log4j
     */
    public void testSfl4jUpLog4j(){
        org.slf4j.Logger logger = LoggerFactory.getLogger(TestLoggers.class.getName());
        logger.info("Slf4j print use log4j");
    }

    /**
     * slf4j-api --> slf4j-jcl --> common-logging-api (自动向log4j)--> log4j
     */
    public void testSlf4j2CommonLogging(){
        org.slf4j.Logger logger = LoggerFactory.getLogger(TestLoggers.class.getName());
        logger.warn("Slf4j print to common logging");
    }

    /**
     * log4j-over-slf4j--> slf4j-api--> logback-classic
     */
    public void testLog4j2Slf4j(){
        org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(TestLoggers.class.getName());
        logger.info("Log4j print to slf4j");
    }

    /**
     * jcl-over-slf4j --> sfl4-api-->logback
     */
    public void testCommonLogging2Sl4j(){
        Log log = LogFactory.getLog(TestLoggers.class.getName());
        log.info("common log to slf4j");
    }

    /**
     * jul(console default)-->jul-to-slf4j-->slf4j-->logback
     * 要在jre/lib/logging.properties 中.handlers添加org.slf4j.bridge.SLF4JBridgeHandler
     */
    public void testJul2Slf4j(){
        java.util.logging.Logger logger = java.util.logging.Logger.getLogger(TestLoggers.class.getName());
        logger.info("jul print to slf4j");
    }

    public static void main(String[] args) {
        TestLoggers tester = new TestLoggers();
        tester.testSlf4j2CommonLogging();
    }
}

  测试maven依赖

 <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.24</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging-api</artifactId>
            <version>1.1</version>
        </dependency>

        <!--<dependency>-->
            <!--<groupId>org.slf4j</groupId>-->
            <!--<artifactId>jcl-over-slf4j</artifactId>-->
            <!--<version>1.7.14</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.7.24</version>
        </dependency>

        <!--<dependency>-->
            <!--<groupId>org.slf4j</groupId>-->
            <!--<artifactId>jul-to-slf4j</artifactId>-->
            <!--<version>1.7.7</version>-->
        <!--</dependency>-->

        <!--<dependency>-->
            <!--<groupId>ch.qos.logback</groupId>-->
            <!--<artifactId>logback-classic</artifactId>-->
            <!--<version>1.2.1</version>-->
        <!--</dependency>-->

        <!--<dependency>-->
            <!--<groupId>org.slf4j</groupId>-->
            <!--<artifactId>slf4j-log4j12</artifactId>-->
            <!--<version>1.7.5</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jcl</artifactId>
            <version>1.7.24</version>
        </dependency>

    </dependencies>

  

参考:

https://www.slf4j.org/legacy.html

https://www.cnblogs.com/chenhongliang/p/5312517.html

原文地址:https://www.cnblogs.com/mutouyihao/p/8151325.html

时间: 2024-10-13 15:06:30

Slf4j与其他日志系统兼容的使用的相关文章

使用 SLF4J + LogBack 构建日志系统(转)

转载自:http://www.cnblogs.com/mailingfeng/p/3499436.html 上次我们讨论了如何选择一个好的开源日志系统方案,其中的结论是:使用 SLF4J + LogBack 是一个很好的选择.这篇文章就来讲讲如何快速地搭建起这套日志系统. 一.简介 LogBack是一个日志框架,它与Log4j可以说是同出一源,都出自Ceki Gülcü之手.(log4j的原型是早前由Ceki Gülcü贡献给Apache基金会的) LogBack.Slf4j.Log4j 之间的

日志之slf4j和logback日志系统(二)

这篇文章我们讲一下,如何使用slf4j和logback组合来搭建一套日志系统. 介绍 如果我们的系统十个新系统,也就是之前没有引入其他的日志工具,那么只需要引入 依赖引入 logback配置文件 业务中使用 学习链接 slf4j源码剖析 原文地址:https://www.cnblogs.com/htyj/p/12023541.html

使用Slf4j集成Log4j2构建项目日志系统的完美解决方案

一.背景 最近因为公司项目性能需要,我们考虑把以前基于的log4j的日志系统重构成基于Slf4j和log4j2的日志系统,因为,使用slf4j可以很好的保证我们的日志系统具有良好的兼容性,兼容当前常见几种日志系统,而使用log4j2而不是log4j是因为Log4j 1.x 在高并发情况下出现死锁导致cpu使用率异常飙升,而Log4j2.0基于LMAX Disruptor的异步日志在多线程环境下性能会远远优于Log4j 1.x和logback(官方数据是10倍以上). 关于slf4j的原理以及优点

slf4j简单日志门面与各种日志系统

SLF4J是为各种loging APIs提供一个简单统一的接口,从而使得最终用户能够在部署的时候配置自己希望的loging APIs实现. 准确的说,slf4j并不是一种具体的日志系统,而是一个用户日志系统的facade,允许用户在部署最终应用时方便的变更其日志系统.在系统开发中,统一按照slf4j的API进行开发,在部署时,选择不同的日志系统包,即可自动转换到不同的日志系统上.比如:选择JDK自带的日志系统,则只需要将slf4j-api-1.5.10.jar和slf4j-jdk14-1.5.1

slf4j日志系统

slf4j SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统. 允许最终用户在部署其应用时使用其所希望的日志系统. 2.如同使用JDBC基本不用考虑具体数据库一样,SLF4J提供了统一的记录日志的接口,只要按照其提供的方法记录即可,最终日志的格式.记录级别.输出方式等通过具体日志系统的配置来实现,因此可以在应用中灵活切换日志系统. 如果你开发的是类库或者嵌入式组件,那么就应该考虑采用SLF4J,因为不

slf4j结合log4j配置日志系统

首先这两个都是日志系统 只不过slf4j是一个简单的门面日志系统简单的来说就是提供了一些列日志接口没有具体的实现类似于jdbc但是比jdbc简单因为 它不需要加载驱动只需要加入其特定的包即可.而log4j自己单独就可以是一个完整的日志系统它提供了自己的实现而不是简单 提供日志接口.下面说说二者的整合. 1.新建一个Java project 2.引入log4j-1.2.15.jar,slf4j-api-1.5.6.jar,slf4j-log4j12-1.5.6.jar三个包 版本不限 3.在项目的

java日志系统 @Slf4j注解的正确使用

在maven项目的pom.xml中添加依赖: <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.5</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <arti

面试题:应用中很多jar包,比如spring、mybatis、redis等等,各自用的日志系统各异,怎么用slf4j统一输出?

一.问题概述 如题所说,后端应用(非spring boot项目)通常用到了很多jar包,比如spring系列.mybatis.hibernate.各类连接数据库的客户端的jar包.可能这个jar包用的是logback.那个用的是log4j.那个又是log4j2, 这时候,怎么才能保证各jar包的日志都能输出,且能以统一的格式输出呢? 为什么要强调非spring boot项目,可参考第四节. 二.几种日志框架的简单介绍 来源:https://juejin.im/post/5a7c5d5751882

java日志框架与日志系统

日志框架:提供日志调用的接口,实际的日志输出委托给日志系统实现. JCL(Jakarta Commons Logging):比较流行的日志框架,很多框架都依赖JCL,例如Spring等. SLF4j:提供新的API,初衷是配合Logback使用,但同时兼容Log4j. 日志系统:负责输出日志 Log4j:较早的日志系统,可以单独使用,也可配合日志框架JCL使用 Logback:Log4j的替代产品,需要配合日志框架SLF4j使用 JUL(java.util.logging):JDK提供的日志系统