深入理解Logger日志——框架绑定原理
深入理解Logger日志——框架绑定原理
说到Logger日志的动态绑定,主要归功与Slf4j,在之前的文章也说过,Slf4j是类似于Apache Common-Logging,英文为Simple Logging Facade,是一个简单的日志门面适配器,所有的日志代码都可以用slf4j方式,它会根据项目具体依赖的日志实现包进行日志操作,只需修改pom.xml文件中的日志实现依赖,对于Log4j、Log4j2和Logback等都有相应的桥接包,对相应的slf4j-api接口实现。
那么slf4j是如何自动绑定上的呢。
多个框架是如何选择的呢。
Slf4j框架架构原理
日志的绑定原理主要是依赖Slf4j的静态加载,从相应的实现框架中获取Logger。需要自己动手一步步跟踪下去才会感触良多。
Slf4j的实现流程:
Logger日志打印调用流程:
在slf4j中主要是实现 LoggerFactoryBinder 的 StaticLoggerBinder 采用单例模式,编译时期静态加载方式,得到不同的ILoggerFactory工厂的实现类,最终拿到相应框架所匹配的Logger。
对于Slf4j的源码分析我这边就不再过多的赘余,关键得自己去理解的看看,推荐一个:Java日志体系(slf4j)
介绍一下slf4j中主要的几个类的作用:
- Logger:slf4j日志接口类,提供了trace < debug < info < warn < error这5个级别对应的方法,主要提供了占位符{}的日志打印方式;
- Log4jLoggerAdapter:Logger适配器,主要对org.apache.log4j.Logger对象的封装,占位符{}日志打印的方式在此类中实现;
- LoggerFactory:日志工厂类,获取实际的日志工厂类,获取相应的日志实现对象;
- lLoggerFactory:底层日志框架中日志工厂的中介,再其实现类中,通过底层日志框架中的日志工厂获取对应的日志对象;
- StaticLoggerBinder:静态日志对象绑定,在编译期确定底层日志框架,获取实际的日志工厂,也就是lLoggerFactory的实现类;
项目中有多种日志框架时会存在多个StaticLoggerBinder时候获取第一个,主要是采用类的顺序加载机制,与Pom文件中依赖的填写顺序有关(个人实践得到)。
每一种日志框架都有相应的桥接包。
首先先看Slf4j-api包结构:主要定义了一些接口做相应的适配,其包结构主要是 org.slf4j 其他实现框架都是根据其进行相应的桥接
Log4j的桥接包形式:相同包名,StaticLoggerBinder采用构造器形式获取 Log4jLoggerFactory 工厂
Logback的桥接包形式:相同包名,在StaticLoggerBinder调用时就已经静态初始化
Logback的详细配置:https://cloud.tencent.com/developer/article/1445599
Log4j2的桥接包形式:相同包名,与Log4j类似采用构造器形式获取 Log4jLoggerFactory 工厂
Log4j2的详细配置:Java日志体系(log4j2)
在官方文档中slf4j与其他日志框架如何绑定的示意图(大家都放我也放一下~)
以下是个人收集一些比较简单好理解的绑定关系图,体现了StaticLoggerBinder绑定的重要性
绑定过程中所遇到的问题
1、Log4j和Log4j2需要配置好log4j.xml和log4j2.xml文件,不然无法正常使用,Logback可以正常使用
2、与SpringBoot的spring-boot-starter中的依赖spring-boot-starter-logging内部的依赖Logback产生冲突(可以自己点击查看一番)
Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.impl.Log4jLoggerFactory loaded from file:/Users/zhouguanglin/.m2/repository/org/slf4j/slf4j-log4j12/1.7.29/slf4j-log4j12-1.7.29.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.impl.Log4jLoggerFactory
at org.springframework.util.Assert.instanceCheckFailed(Assert.java:699)
at org.springframework.util.Assert.isInstanceOf(Assert.java:599)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:284)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:104)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:232)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:213)
主要原因是:SpringBoot所使用的搭配日志框架是Logback
若是项目使用SpringBoot但搭配的是其他日志框架A,由StaticLoggerBinder.getSingleton().getLoggerFactory()获取的是搭配框架A的实现,导致与SpringBoot内部自身搭配的Logback产生冲突,可以进入报错地方查看。
从代码逻辑中可以发现,Assert.isInstanceOf 判断获取得到的ILoggerFactory的实现类必须是LoggerContext 才OK,硬性规定不然就会报错。
解决方案:只要在SpringBoot中排除Logback的依赖就OK,如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
</exclusions>
</dependency>
深入理解Logger日志——框架绑定原理的更多相关文章
- slf4j日志框架绑定机制
一.环境搭建 我们以log4j为例,探寻slf4j与log4j的绑定过程. 1.Java类 public class Slf4jBind { public static void main(Strin ...
- 深入理解List集合框架底层原理的实现
前言: 此篇文章讲解ArrayList和LinkedList底层实现原理.for和foreach遍历集合哪个效率会更高一些! 讲讲什么是集合框架?集合框架是为表示和操作集合而规定的一种统一的标准的体系 ...
- Slf4j+Log4j日志框架入门
(一).日志系统介绍 slf4j,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统.简答的讲就是slf4j是一系列的 ...
- Java日志框架Slf4j+Log4j入门
一.日志系统介绍 slf4j,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统.简答的讲就是slf4j是一系列的日志 ...
- Java日志框架:slf4j作用及其实现原理
简单回顾门面模式 slf4j是门面模式的典型应用,因此在讲slf4j前,我们先简单回顾一下门面模式, 门面模式,其核心为外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用.用一 ...
- SpringBoot系列之日志框架介绍及其原理简介
SpringBoot系列之日志框架介绍及其原理简介 1.常用日志框架简介 市面上常用日志框架:JUL.JCL.jboss-logging.logback.log4j.log4j2.slf4j.etc. ...
- Moon转告给你一个比Log4net更好日志框架--TracerX Logger 及其对应的日志查看器
一.介绍 TracerX logger是一个易于上手,且拥有众多高级特性的.NET日志框架. 它能够发送输出结果到多目的地(循环文件.事件日志等....).它也能生成文本和二进制文件.它拥有一个强大的 ...
- springBoot日志框架自动配置与原理
1.日志框架 小张:开发一个大型系统: 1.System.out.println(""):将关键数据打印在控制台:去掉?写在一个文件? 2.框架来记录系统的一些运行时信息: ...
- 大幅度改变celery日志外观,修改成日志可点击跳转和鲜艳五彩日志,解决脚本中已添加handler的logger和框架日志重复记录问题。
大幅度改变celery日志外观,修改成日志可点击跳转和鲜艳五彩日志,解决脚本中已添加handler的logger和框架日志重复记录问题.打猴子补丁. 先把脚本中的所有logger的handlers全部 ...
随机推荐
- [BUUOJ记录] [GXYCTF2019]BabySQli
有点脑洞的题,题目不难,主要考察注入和联合查询的一个小特点 进入题目是一个登录框,看看源代码,在search.php文件中发现了这个 大写的字母和数字很明显是base32,先用base32解码一下,发 ...
- Spark3.0YarnCluster模式任务提交流程源码分析
1.通过spark-submit脚本提交spark程序 在spark-submit脚本里面执行了SparkSubmit类的main方法 2.运行SparkSubmit类的main方法 3.调用doSu ...
- 轻轻松松学CSS:媒体查询
轻轻松松学CSS:利用媒体查询创建响应式布局 媒体查询,针对不同的媒体类型定制不同的样式规则.在网站开发中,可以创建响应式布局. 一.初步认识媒体查询在响应式布局中的应用 下面实例在屏幕可视窗口尺寸大 ...
- C010:书号分解ISBN
代码: #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { int prefix,groupIndentifier ...
- MySQL查询point类型类型的坐标,返回经度纬度
location字段为point类型的空间坐标 SELECT id, name, address, x(location) as 经度, Y(location) as 纬度, ROUND( 6378. ...
- 前端插入date类型的数据到数据库
//插入 @Override public boolean insertEmp(Emp emp) { String sql = "insert into emp(lwlEmpno,lwlEn ...
- matplotlib | Python强大的作图工具,让你从此驾驭图表
今天是数据处理专题的第9篇文章,在之前的8篇文章当中我们已经介绍完了pandas这个库的一些基本用法,我们先把一些冷门的高级用法放一放,先来给大家介绍一下另外一个很有用的数据分析库--matplotl ...
- 轻松上手SpringBoot Security + JWT Hello World示例
前言 在本教程中,我们将开发一个Spring Boot应用程序,该应用程序使用JWT身份验证来保护公开的REST API.在此示例中,我们将使用硬编码的用户和密码进行用户身份验证. 在下一个教程中,我 ...
- WebGL之延迟着色
什么是延迟着色(Deferred Shading)?它是相对于正常使用的正向着色(Forward Shading)而言的,正向着色的工作模式:遍历光源,获取光照条件,接着遍历物体,获取物体的几何数据, ...
- docker 搭建私有云仓库
docker搭建私有仓库 registry私有仓库 下载docker-distribution软件包 yum install epel-release yum install docker-dis ...