Java日志体系 —— slf4j

1.1 简介

                    

与commons-logging相同,slf4j也是一个通用的日志接口,在程序中与其他日志框架结合使用,并对外提供服务。

Simple Logging Facade for Java简称 slf4j,Java简单日志门面系统。在我们的代码中,不需要显式指定具体日志框架(例如:java.util.logging、logback、log4j),而是使用slf4j的API来记录日志便可,最终日志的格式、记录级别、输出方式等通过具体日志框架的配置来实现,因此可以在应用中灵活切换日志系统。

如果你对上面所说的,仍然不太理解。那么,简单的说slf4j可以理解为JDBC,都是提供接口服务,只不过比JDBC更为直观、简单些。在程序中,JDBC需要单独指定具体的数据库实现(例如:mysql),而slf4j并不需要。

接下来,我们讲解下关于slf4j具体的使用。

1.2 slf4j结构

              

上面的截图,展示的是slf4j搭配log4j使用。

Logger:slf4j日志接口类,提供了trace < debug < info < warn < error这5个级别对应的方法,主要提供了占位符{}的日志打印方式;

Log4jLoggerAdapter:Logger适配器,主要对org.apache.log4j.Logger对象的封装,占位符{}日志打印的方式在此类中实现;

LoggerFactory:日志工厂类,获取实际的日志工厂类,获取相应的日志实现对象;

lLoggerFactory:底层日志框架中日志工厂的中介,再其实现类中,通过底层日志框架中的日志工厂获取对应的日志对象;

StaticLoggerBinder:静态日志对象绑定,在编译期确定底层日志框架,获取实际的日志工厂,也就是lLoggerFactory的实现类;

1.3 使用

同为Java日志接口框架,相对于commons-logging来说,slf4j的使用有点特殊。

在第一篇的文章中,笔者介绍了commons-logging的使用,对于commons-logging来说,无需在pom.xml文件中单独引入日志实现框架,便可进行日志打印。但是,slf4j并不支持此功能,必须在pom.xml中单独引入底层日志实现。

搭配log4j使用:
首先,需要在pom.xml文件中添加依赖:

//slf4j:
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.20</version>
</dependency>

//slf4j-log4j:
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.12</version>
</dependency>

//log4j:
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

声明测试代码:

public class slf4j_log4jDemo {

    Logger logger = LoggerFactory.getLogger(slf4j_log4jDemo.class);

    @Test
    public void test() throws IOException {
        logger.error("Error Message!");
        logger.warn("Warn Message!");
        logger.info("Info Message!{}","你好");
        logger.debug("Debug Message!");
        logger.trace("Trace Message!");
    }
}

接下来,在classpath下定义配置文件:log4j.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <param name="ImmediateFlush" value="true"/>
        <param name="encoding" value="UTF-8"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %t %-5p (%c:%L) - %m%n"/>
        </layout>
    </appender>
    <root>
        <priority value="debug" />
        <appender-ref ref="CONSOLE" />
    </root>
</log4j:configuration>

对于slf4j来说,它只提供了一个核心模块--slf4j-api,这个模块下只有日志接口,没有具体的实现,所以在实际开发总需要单独添加底层日志实现。但是,这些底层日志类实际上跟slf4j并没有任何关系,因此slf4j又通过增加一层日志中间层来转换相应的实现,例如上文中的slf4j-log4j12。

上图,是官方文档中slf4j与其他日志框架相结合的使用情况,具体总结如下:

logback:logback-classic 、logback-core

java.util.logging.Logging:slf4j-jdk14

commons-logging:jcl-over-slf4j

其中,commons-logging比较特殊。由于commons-logging诞生的比较早,一些年限久远的系统大体上都使用了commons-logging和log4j的日志框架组合,大名鼎鼎的spring框架也依然在使用commons-logging框架。那么,此时你的新系统如果想使用slf4j该如何处理?

这会,就需要引入jcl-over-slf4j.jar包了,它会将commons-logging的“骗入”到slf4j中来,实现日志框架结合;

1.4 slf4j静态绑定原理

虽然commons-logging和slf4j都是日志服务接口,但是两者对于底层日志框架绑定的方式相差甚远。在第一篇日志系统的文章中,笔者已经介绍过,commons-logging是基于动态绑定来实现与日志框架的结合,也就是说在编译期间我们的程序并不知道底层的实现是什么,只有在运行期间才进行获取;

与commons-logging不同的是,slf4j是基于静态绑定来实现与日志框架的结合,在编译期间我们的程序就已经知道使用了哪种日志实现。

1.5 slf4j和commons-logging比较

(1)slf4j使用了静态绑定方式,实现了与底层日志框架的结合, 避免了commons-logging中由于类加载器不同导致的日志加载失败情况的发生;

(2)slf4j支持参数化日志打印,也就是占位符{}的方式。去除了commons-logging中的isDebugEnabled(), isInfoEnabled()等方法的日志级别检查代码,极大的提高了代码可读性;并且,占位符的方式也延缓了构建日志信息(String的开销),提高了内存的使用性;

在commons-logging中,我们经常需要些这样的代码:

if (logger.isDebugEnabled()) {
    logger.debug("我是: " + name);
}

而在slf4j中,我们可以这样写:

logger.debug("我是: {}",name);

在commons-logging中,是要符合日记级别,我们就进行字符串的拼接;而在slf4j中,我们不进行字符串拼接操作,而是使用StringBuffer来完成的替换。这不仅降低了内存消耗而且预先降低了CPU去处理字符串连接命令的时间,提高了程序的性能。

1.6 slf4j搭配commons-logging使用原理

在前面的小节中,我们提到了slf4j为了兼容老代码,是可以跟commons-logging结合使用的,需要在pom.xml文件中引入jcl-over-slf4j.jar包。具体实现过程如下:

测试代码:(引入的依旧为commons-logging对象,无需改变)

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;

public class commons_loggingDemo {
    Log log= LogFactory.getLog(commons_loggingDemo.class);
    @Test
    public void test() throws IOException {
        log.debug("Debug info.");
        log.info("Info info");
        log.warn("Warn info你好");
        log.error("Error info");
        log.fatal("Fatal info");
    }
}

引入pom依赖:(除了原有的commons-logging和log4j依赖外,还需要添加slf4j-api、jcl-over-slf4j、slf4j-log4j12依赖)

!-- commons-logging -->
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.1.3</version>
</dependency>

<!--将commons-logging引入到slf4j中去-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>1.7.20</version>
</dependency>

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

 <!--slf4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.20</version>
</dependency>

日志配置文件: (均为commons-logging时期配置,无需为slf4j做任何改变)

commons-logging.properties配置文件:
#日志对象:
org.apache.commons.logging.Log=org.apache.log4j.Logger
#日志工厂:
org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl

log4j.xml配置文件:
<log4j:configuration>
    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <param name="ImmediateFlush" value="true"/>
        <param name="encoding" value="UTF-8"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %t %-5p (%c:%L) - %m%n"/>
        </layout>
    </appender>
    <root>
        <priority value="debug" />
        <appender-ref ref="CONSOLE" />
    </root>
</log4j:configuration>

实现原理:

将commons-logging的输出引入到jcl-over-slf4j中,再转向slf4j,紧接着进入到slf4j-log4j12,最终进入到log4j;

参考:https://www.jianshu.com/p/e3b2de9e418b

原文地址:https://www.cnblogs.com/caoweixiong/p/11273378.html

时间: 2024-08-04 20:27:28

Java日志体系 —— slf4j的相关文章

Java 日志体系(二)jcl 和 slf4j

Java 日志体系(二)jcl 和 slf4j <java 日志体系(一)统一日志>:https://www.cnblogs.com/binarylei/p/9828166.html <Java 日志体系(二)jcl 和 slf4j>:https://www.cnblogs.com/binarylei/p/10781582.html 前面介绍了 jdk 自带的 logging.log4j1.log4j2.logback 等实际的日志框架.对于开发者而言,每种日志都有不同的写法.如果

混乱的 Java 日志体系

混乱的 Java 日志体系 2016/09/10 | 分类: 基础技术 | 0 条评论 | 标签: LOG 分享到: 原文出处: xirong 一.困扰的疑惑 目前的日志框架有 jdk 自带的 logging,log4j1.log4j2.logback ,这些框架都自己定制了日志 API ,并且有相应的实现:目前用于实现日志统一的框架 Apache commons-logging.slf4j ,遵循「面向接口编程」的原则,这两大框架可以让用户在程序运行期间去选择具体的日志实现系统(log4j1\

Java日志体系居然这么复杂?——架构篇

摘自:https://www.cnblogs.com/xuningfans/p/12151851.html 本文是一个系列,欢迎关注 日志到底是何方神圣?为什么要使用日志框架? 想必大家都有过使用System.out来进行输出调试,开发开发环境下这样做当然很方便,但是线上这样做就有麻烦了: 系统一直运行,输出越来越多,磁盘空间逐渐被写满 不同的业务想要把日志输出在不同的位置 有些场合为了更高性能,尽量控制减少日志输出,需要动态调整日志输出量 自动输出日志相关信息,比如:日期.线程.方法名称等等

Java 日志体系

参考资料: 混乱的 Java 日志体系 Java常用日志框架介绍 Java常用的日志框架对比和深入分析

Java日志体系 —— logback

1.1 简介 师出同门,与log4j一样,logback也是由Ceki Gülcü开发的开源日志组件,可以说是log4j的改进版:在现如今的项目中,logback的出现次数越来越多,是目前主流首选的日志记录工具. 1.2 logback结构 logback分成三个模块:logback-core,logback- classic,logback-access. logback-core提供了logBack的核心功能,是另外两个组件的基础: logback-classic模块实现了SLF4J API

Java日志:集成slf4j和logback

Java日志方案有很多,包括:java.util.logging.Apache的commons-logging和log4j.slf4j以及logback. 一个大型项目会用到众多第三方jar包,这些jar包可能会用到上述各种日志方案,如何在新的项目中使用slf4j+logback的组合,让所有其他jar包的日志也输出到logback,并避免冲突和异常? SLF4J is a simple facade for logging systems allowing the end-user to pl

架构师必备,带你弄清混乱的JAVA日志体系

引言还在为弄不清 commons-logging-xx.jar . log4j-xx.jar . sl4j-api-xx.jar 等日志框架之间复杂的关系而感到烦恼吗? 还在为如何统一系统的日志输出而感到不知所措嘛? 您是否依然存在这样的烦恼.比如,要更改spring的日志输出为log4j 2,却不知该引哪些jar包,只知道去百度一下所谓的博客,照着人家复制,却无法弄懂其中的原理? 不要急,不要方!本文带你们弄懂其中的原理,只要你静下心看本文,你就能随心所欲更改你系统里的日志框架,统一日志输出!

java日志之slf4j与logback简单使用

最近在开发遇到日志是使用slf4j与logback.xml的配置,所以就记录下来了. 1.导入这几个jar包: Logback 分为三个模块:logback-core,logback-classic,logback-access logback-core 是核心: logback-classic 改善了 log4j,且自身实现了 SLF4J API,所以即使用 Logback 你仍然可以使用其他的日志实现,如原始的 Log4J,java.util.logging 等: logback-acces

java日志框架slf4j与log4j的使用与配置

日志记录自然是非常重要的,但恐怕能记住slf4j与log4j等日志框架配置的人就很少了,这个东西不难,只是配置好后很少会去动它,开发新项目一般也是从其他项目拷贝,或者参照文档 废话不多说,先说log4j,使用log4j只要简单的几步 首先,弄到log4j的jar包,maven工程配置以下依赖就行,或者,从阿里的maven仓库下载jar包,添加到工程的"build path" <dependency> <groupId>log4j</groupId>