Log 之slf4j

3 篇文章 0 订阅
SLF4J是简单日志门面,提供统一的日志记录接口,允许在部署时选择不同的日志系统。本文介绍了SLF4J的基本概念,主流的日志框架如JUL、JCL、log4j、logback和log4j2,并详细阐述了SLF4J如何通过直接实现和适配器层与这些日志框架交互。在项目中,根据需求导入相应的直接实现或适配层依赖即可实现日志系统的灵活切换。
摘要由CSDN通过智能技术生成

1.slf4j的概念

近期学习springboot的时候,其中的日志模块 spring-boot-logging-starter,springboot 底层的日志实现默认是 slf4j + logback。我一直很好奇springboot 集成了 怎么多的框架,而每个框架的自身实现的日志又不一样如(spring 采用的是 common-logging ,hibernate 采用的是jboss-logging等),那他又是怎么实现日志统一的呢?然后就细细看了一下springboot的文档,springboot大概的意思就是 用slf4j 做抽象层,然后用logback 做实现层,在引入第三方依赖的时候,将原有的日志依赖排除。。。 顿时感觉脑袋有点晕晕,然后硬着头皮的读了一下slf4j文档。
首先我们的了解一下什么是slf4j? 度娘的说法是
slf4j百度百科
SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志System
实际上,SLF4J所提供的核心API是一些接口以及一个LoggerFactory的工厂类。从某种程度上,SLF4J有点类似JDBC,不过比JDBC更简单,在JDBC中,你需要指定驱动程序,而在使用SLF4J的时候,不需要在代码中或配置文件中指定你打算使用那个具体的日志系统。如同使用JDBC基本不用考虑具体数据库一样,SLF4J提供了统一的记录日志的接口,只要按照其提供的方法记录即可,最终日志的格式、记录级别、输出方式等通过具体日志系统的配置来实现,因此可以在应用中灵活切换日志系统。
看到Jdbc 大家有点感悟了,原来 slf4j是干这活的。顿时想起在导jar包到lib目录下搭建项目环境, 导入slf4j-api-jar 还要引起他的依赖如log4j等的血泪史了。

2.slf4j底层实现日志记录的几种方式

上文说道 slf4j 主要是充当日志门面的角色,日志具体实现还是开发者自己决定的。那现在主流的日志框架有哪些呢?

2.1 主流的日志框架

  • JUL(java.util.logging) java内置的日志模块
  • JCL(Jakarta Commons Logging) 也叫Apache Commons Logging其中spring就是用的这个实现日志记录的
  • log4j (Log4j是Apache的一个开源项目) 是一个日志功能比较强大的日志记录器
  • logback是log4j的升级版,由三个模块组成:logback-core, logback-classic and logback-access。 其中logback-core为另外两个模块提供了基础,logback-classic是 log4j的改进版和实现slf4j。
  • log4j2 是现在市面上功能最强大的日志记录器,和log4j是两个框架并不是log4j的升级版。只是借用了一下log4j的名称而已。
  • Jboss-logging(用得很少忽略)

2.2 这几种主流的日志框架的实现

我们了解了常用的几种日志实现框架。但是在项目中我们该怎么用呢?上面我们提到过 slf4j是简单日志门面是抽象层,针对开发者在代码中编写的,那我们在代码中应该怎么写呢?其实我们实现起来很简单 在slf4j的用户手册中有一个hello world的入门程序

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");
  }
}

我们只把当前类.class 作为参数传给LoggerFactory,由日志工厂给我们生产出一个日志记录器 Logger ,然后就可以通过logger.info(),
logger.error()来实现日志记录功能。但是它底层是怎么实现的呢?

slf4j官方文档中有一个图片就阐述了这一过程
这里写图片描述

在这个图片中我们可以大概的了解到通过slf4j日志记录大分不同日志实现有不同日志实现架构(api —slf4j直接实现/ 适配器层— 第三方日志记录器)。其中slf4j直接实现 和适配层是最为关键的一步:
我们可以从两个方面来阐述他的重要性:如 loggback为例
a.从代码层面:
这里写图片描述
从上图中我们可以看出logback.claassic里的LoggerContext直接实现了slf4j的getLogger 。这就是slf4j的本地实现。

b.从架构方面(导入依赖)
这里写图片描述

其中logback-classic这层就依赖 slf4j-api 以及 logback-core ,我们可以认为slf4j的直接实现层 把 slf4j-api 层以及 日志实现做了处理,所以我们导入依赖的时候 由依赖的传递性,我们只需要导入 这个logback-classic 依赖就可以了。

适配层也可以这样分析:
代码层面:

public class Log4jLoggerFactory implements ILoggerFactory {
    private static final String LOG4J_DELEGATION_LOOP_URL = "http://www.slf4j.org/codes.html#log4jDelegationLoop";
    ConcurrentMap<String, Logger> loggerMap = new ConcurrentHashMap();

    public Log4jLoggerFactory() {
        LogManager.getRootLogger();
    }

    public Logger getLogger(String name) {
        Logger slf4jLogger = (Logger)this.loggerMap.get(name);
        if(slf4jLogger != null) {
            return slf4jLogger;
        } else {
        //这里底层就采用的log4j来实现的
            org.apache.log4j.Logger log4jLogger;
            if(name.equalsIgnoreCase("ROOT")) {
                log4jLogger = LogManager.getRootLogger();
            } else {
                log4jLogger = LogManager.getLogger(name);
            }

            Logger newInstance = new Log4jLoggerAdapter(log4jLogger);
            Logger oldInstance = (Logger)this.loggerMap.putIfAbsent(name, newInstance);
            return (Logger)(oldInstance == null?newInstance:oldInstance);
        }
    }

架构层次:
这里写图片描述

1.如果只有slf4j,而没有其他日志实现框架,会报错

throwing a NoClassDefFoundError because the org.slf4j.impl.StaticLoggerBinder class is missing

2.如果你想用 logback 做为日志实现,我们只要导入slf4j直接实现层依赖就可以

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

3.如果你想用 log4j的话 ,我们只要导入适配层依赖就可以使用:

<dependency> 
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.8.0-beta2</version>
</dependency>

4.如果要想用jdk自带的日志模块,同理我们只要导入中间适配层的依赖

<dependency> 
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-jdk14</artifactId>
  <version>1.8.0-beta2</version>
</dependency>

5.同理如果你想用其他实现框架,同理我们只要导入slf4j直接实现层或者适配层依赖就可以。

3. 导入依赖总结

从上文中对slf4j的直接实现层与适配层的分析,我们可以得出一个结论,我们想要用哪个实现框架就 参照slf4j的官方文档 导入对应得slf4j直接实现层依赖或者适配层依赖就可以。当然这只是针对Maven 等构建工具;如果还是导jar的方式,那就。。。

这篇博客只是让我们了解了一下slf4j在项目中的使用以及不同具体日志实现框架的项目环境搭建。我们在下章我将深入的了解一下logback 的功能以及配置。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值