日志框架 SLF4j

是什么:

SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统

为什么:

在java.util.logging, logback, log4j等日志系统存在的基础上,为什么要用slf4j框架作为一个门面呢?

SLF4J 是一个日志抽象层,允许你使用任何一个日志系统,并且可以随时切换还不需要动到已经写好的程序。这对于第三方组件的引入的不同日志系统来说几乎零学习成本了,况且它的优点不仅仅这一个而已,还有简洁的占位符的使用和日志级别的判断,众所周知的日志读写一定会影响系统的性能,但这些特性都是对系统性能友好的。

怎么用:

只需要在maven中引入slf4j的依赖:

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

引入你需要使用的日志系统的依赖,由于log4j需要配置文件,为了方便,选用了其他的一些日志系统:

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-simple</artifactId>
			<version>1.7.22</version>
		</dependency>

在代码中即可:

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

看一下打印的日志:

如果需要更换日志系统时,只需要将相关的日志系统的依赖替换即可。这儿选择替换成了

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

再看一下同样的代码打印出来的日志:

是不是日志系统切换很方便,没有侵入性呢?这也就是slf4j这么推荐的原因。

阿里巴巴 Java 开发手册有这么一段:

【强制】应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架
SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Abc.class);

如何实现

那这个slf4j这么方便,是如何做到的呢?可以通过LoggerFactory.getLogger进去看一下他的实现原理:进入该方法后


可以获取logger的工厂,通过工厂获取该实例。

那是如何根据引入的jar包来动态获取logger工厂的呢?初始化的时候

if (INITIALIZATION_STATE == UNINITIALIZED) {...} 该条件是成立的,所以会进行初始化

下面这个bind方法为关键的方法

看一下bind方法的具体实现,标红的方法会找到可能的logger的path集合:

跟进去看一下,系统会扫描org/slf4j/impl/StaticLoggerBinder.class,并放入一个集合。

可以猜想一下:是不是所有的日志系统里都有这个类呢?可以看一下:

在获取到日志系统staticLoggerBinder.class的集合后,如果同时引入了多个日志系统,reportMultipleBindingAmbiguity方法中会打印出warn日志。

真正绑定的是下面的一行代码:

StaticLoggerBinder.getSingleton();

看一下该类的引用:

import org.slf4j.impl.StaticLoggerBinder;

但是该类StaticLoggerBinder在slf4j的jar包中并没有,org.slf4j.impl这个包也没有。而是引用的具体日志系统中的StaticLoggerBinder。如果没有引用具体的日志系统的话,就会出现catch中的警告:

有了StaticLoggerBinder这个类之后。通过

StaticLoggerBinder.getSingleton().getLoggerFactory(),不同的StaticLoggerBinder其getLoggerFactory实现不同,拿到ILoggerFactory之后调用一下getLogger即拿到了具体的Logger,可以使用Logger进行日志输出。

热门文章

暂无图片
编程学习 ·

springboot+idea+bootstrap的带有图片的表格编辑操作

前面已经写了 批量导入,图片显示,现在写的是批量修改,后面会写用echarts+springboot 做折线图,有时间贴上 1、jsp代码如下,编辑按钮formatter: function (value, row, index) {var edit = <input class="btn btn-primary" type="button" value=&qu…
暂无图片
编程学习 ·

2 css

css的三大特性 css有三个非常重要的三个特性;层叠性 继承性 优先级 层叠性 相同选择器给设置相同的样式,此时一个样式就会覆盖(层叠)另一个冲突的样式,层叠性 主要解决样式冲突的问题 原则 样式冲突,遵循原则上就近原则,那个样式离结构近,就执行那个样式 样式不冲突,不…
暂无图片
编程学习 ·

内网穿透工具 frp

内网穿透工具 frp 荐国网络工具包授权协议: GPL开发语言: Google Go操作系统: 跨平台收录时间: 2016-08-01提 交 者: FateDier收藏1145评论62分享软件介绍资讯 (8)问答 (2)博客 (99+)我要提问frp 是一个高性能的反向代理应用,可以帮助您轻松地进行内网穿透,对外网提供服务,支…
暂无图片
编程学习 ·

nginx+tomcat 配置证书

nginx 配置证书 tomcat 配置文件说明#user nobody; worker_processes 1;#error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info;#pid logs/nginx.pid;events {worker_connections 1024; }http {include mime.typ…
暂无图片
编程学习 ·

两种判断对象类型的方法

两种判断对象类型的方法: 1.通过instanceof *缺点:不能准确的判断该对象是Dog的实例,如果该对象是类的子类对象也会返回true 2.对象.getClass().getName()获取对象的实例类名 (1)对象.getClass():返回该对象对应的Class对象 (2)对象.getClass().getName():该对象对应的class对…
暂无图片
编程学习 ·

Web服务器防护技术你了解多少?

技术的迅速发展,给人们提供便利的同时,也给人们带来了威胁。通常情况下,黑客、病毒会利用系统的漏洞来进行网络攻击,如篡改网页、蔓延病毒等,从而造成用户信息的窃取、重要数据的破坏。因此,要对web服务器的安全问题引起足够的重视,要加大安全防护力度、构建安全防护系统…
暂无图片
编程学习 ·

Python中%r和%s的相同点和不同点

1、在处理布尔型或者数字型时,二者是没有区别的 (1)数字型 I am %r years old%22#%r ‘I am 22 years old’ I am %s years old%22#%s‘I am 22 years old’ This building is %r m tall%22.35#%r‘This building is 22.35 m tall’ This building is %s m tall%22.35#%s‘Thi…
暂无图片
编程学习 ·

单调栈解决Next Greater Number一类题

单调栈是什么? 单调栈使得每次新元素入栈后,栈内元素都保持有序(单调递增或者单调递减)。 单调递增栈:栈中数据出栈的序列为单调递增序列。 单调递减栈:栈中数据出栈的序列为单调递减序列。 注意:这里所说的递增递减是出栈的顺序,不是栈中数据的顺序。 单调栈的应用 通…
暂无图片
编程学习 ·

ubuntu python 升级 和pip匹配问题

ubuntu16.04,卸载系统自带的python3.5引发了一宗惨案,好在最终完美解决https://blog.csdn.net/qq_29935433/article/details/105568942?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribut…
暂无图片
编程学习 ·

设计模式学习——单例模式

一、单例模式的概念1.1 概念单例模式是指 确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。单例模式的特点是隐藏其所有的构造方法。属于创建型模式。1.2 单例模式的适用场景确保任何情况下都绝对只有一个实例。例如ServletContext、ServletConfig、Applicat…
暂无图片
编程学习 ·

【Hadoop篇08】Hadoop数据压缩

简洁而不简单Hadoop数据压缩 数据压缩优点和缺点 ​ 压缩技术能够有效减少底层存储系统(HDFS)读写字节数。压缩提高了网络带宽和磁盘空间的效率。在 Hadoop下,尤其是数据规模很大和工作负载密集的情况下,使用数据压缩显得非常重要。在这种情况下,IO操作和网络数据传输要…
暂无图片
编程学习 ·

在Eclipse EE上搭建基于Scala文件的Maven项目

在Eclipse EE上搭建基于Scala文件的Maven项目这篇博客是笔者在进行创新实训课程项目时所做工作的回顾。对于该课程项目所有的工作记录,读者可以参阅下面的链接。 注意!这篇博文不会涉及在机器上安装Hadoop,Spark等环境,仅仅是能够在Eclipse EE上搭建基于Scala文件的Maven项…
暂无图片
编程学习 ·

跟汤老师学Java笔记:文件字节输入输出流

跟汤老师学Java笔记:文件字节输入输出流 完成:第一遍 1.文件字节输入流创建和常用方法有哪些? 创建:构造参数有字符串和File对象两种 方法: 方法:fis.read() 作用:读取一个字节,返回int类型的字节值,如果读取到末尾返回-1 方法:fis.close() 作用:输入流用了操作系统…
暂无图片
编程学习 ·

MySQL配置文件

MySQL配置文件 1.配置环境变量 新建MYSQL_HOME变量,变量值是包的路径。 2.然后再path中添加:%MYSQL_HOME%\bin 3.执行mysqld install命令当出现Service successfully installed时表示mysql服务安装完成 4.MySQL初始化 :输入: mysqld --initialize --console 执行完成后,会…
暂无图片
编程学习 ·

迭代器

概念 提供对对象的间接访问,有效的迭代器或者指向某个元素,或者指向容器中尾元素的下一位置 使用 获取 begin()返回指向第一个元素/字符的迭代器 end()返回指向容器(或string)尾元素的下一位置即根本不存在的尾后元素解引用 如it为vector对象的迭代器:(*it).empty()或者it-&…
暂无图片
编程学习 ·

组合数学4-全排列与算法

文章目录全排列与算法一 钟声里的全排列**思考**:生成算法二 字典序法1.递归2.字典序法例1:生成字母abc的全排列例2:生成123的全排列例3:生成839647521的全排列3.**思考**:局部连续变化三 SJT算法(Steinhaus–Johnson–Trotter algorithm)1. 引出思路2. 可移动数(mobil…
暂无图片
编程学习 ·

flex布局,左右两端固定,中间自适应且超出隐藏

这几个月来,在样式上备受打击,感觉自己css都不会写。有需求要flex布局,左右两端固定,中间自适应且超出隐藏,我百度加自己整理下,记录下来。 这个是flex布局,左右两端固定,中间自适应 //html代码 <div class="parent"><div class="left"&g…
暂无图片
编程学习 ·

用C语言解一元二次方程式的根

#include<stdio.h> #include<math.h> //需要用到一个sqrt()函数,该函数功能用于开方;//该函数运算结果数据类型为double类型;如果涉及到运算请将数据类型定义成浮点型! int main () {float a,b,c,x1,x2;printf("请分别输出方程式的系数,中间以空格分隔\n&…