设为首页 加入收藏

TOP

委派模式——从SLF4J说起(一)
2023-07-25 21:43:47 】 浏览:70
Tags:SLF4J 说起

作者:vivo 互联网服务器团队- Xiong yangxin

将某个通用解决方案包装成成熟的工具包,是每一个技术建设工作者必须思考且必须解决的问题。本文从业内流行的既有工具包入手,解析实现思路,沉淀一般方法。为技术建设的初学者提供一些实践思路的参考。尤其是文中提倡的“去中心化”的协作模式,和“关键链路+开发接口”的开发模式,具有一定的实际落地意义。当然本文在行文中,不可避免存在一定主观偏见性,读者可酌情阅读。

一、前言

熟悉JAVA服务器开发的同学应该都使用过日志模块,并且大概率使用过"log4j-over-slf4j"和“slf4j-log4j”这两个包。那么这两个包的区别是什么?为什么会互相引用包含呢?这篇文章会解释下这几个概念的区别。

首先说一下SLF4J

二、从SLF4J开始

SLF4J全称"Simple Logging Facade for Java (SLF4J) ", 它诞生之初的目的,是为了针对不同的log解决方案,提供一套统一的接口适配标准,从而让业务代码无须关心使用到的第三方模块都使用了哪些log方案。

举个例子, Apache Dubbo和RabbitMQ使用到的日志模块便不相同。从某种意义上而言,SLF4J只是一个facade,类似于当年的ODBC(针对不同的数据库厂商而制定的统一接口标准, 下文会涉及到)。而这个facade对应的包名,是 “slf4j-api-xxx.xxx.xxx.jar”。所以,当你应用了"slf4j-api-xxx.jar"的包时,其实只是引入了一个日志接口标准,而并没有引入日志具体实现

2.1、业内实现

SLF4J标准在应用层的核心类,就是两个: org.slf4j.Logger 和 org.slf4j.LoggerFactory。其中,自版本1.6.0后,如果并没有具体的实现,slf4j-api会默认提供一个啥也不干的Logger实现(org.slf4j.helpers.NOPLogger)。

在当前(本稿件于2022-03-01拟制)的市面上,既有的实现SLF4J的方案有以下几种:

图片

整体层次如下图:

图片

 

综上而言:以SLF4J-开头的jar包,一般指的是采用某种第三方框架实现的slf4j解决方案。

2.2 工作机制

那么整个SLF4J的工作机制是如何运作的呢,换句话说,系统是如何知道应该使用哪个实现方案的呢?

对于那种不需要适配器的原生实现方式,直接引入对应的包即可。

对于那种需要适配器的委托式实现方式,则需要通过另外的一个渠道来告知SLF4J应该使用哪个实现类: SPI机制。

举个例子,我们看一下slf4j-log4j的包结构:

图片

我们先看pom文件,就包含两个依赖:

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

<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>

slf4j-log4j同时引入了slf4j-api和log4j。那么slf4j-log4j本身的作用不言而喻:使用LOG4j的功能,实现SLF4J的接口标准。

整体的接口/类关系路径如下图:

图片

但是这仍然没有解决本章节开始提出的问题(程序怎么知道应该用哪个Logger)。

可以从源码入手:(slf4j/slf4j-log4j12 at master · qos-ch/slf4j · GitHub),我们看到了以下关键的文件:

图片

 

也就是说:slf4j-log4j使用了java的SPI机制告知JVM在运行时调用具体哪一个实现类。由于SPI机制暂不属于本文章讨论范围,读者可以去官网获取信息。

读者可以去GitHub - qos-ch/slf4j: Simple Logging Facade for Java看其他的实现方式的适配器是如何工作的。

那么本章开始的问题答案便是:

  1. SLF4J制定一套日志打印流程,然后把核心类抽象出接口给外部去实现;

  2. 适配器使用第三方日志组件实现了这些核心类接口,并采用SPI机制,让JAVA运行时意识到核心接口的具体实现类。

而上述两点,构成了本文接下来要讲述的知识点:委派模式。

三、委派模式

从上文中,我们从SLF4J的案例,引出了"委派模式"这个概念,下面我们就重点讨论委派模式(delegation)。

接下来我们按照认知流程,依次从三个问题,解释委派模式:

  • 为什么使用委派模式

  • 什么是委派模式

  • 如何使用委派模式

然后会在下一章,用业内的典型案例,分析委派模式的使用情况。

3.1 为什么采用委派模式?

我们回到SLF4J。为什么它会用委派模式呢?因为日志打印功能存在各种不同的实现方式。对于应用开发者而言,最好需要一个标准的打印流程,其他第三方组件可以在某些地方有些不同,但是核心流程是最好不要变。对于标准制定者 而言,他无法控制每一个第三方组件的所有细节,所以只能暴露出有限的自定制能力。

而我们放大到软件领域,或者在互联网开发领域,不同的开发者的协作模式,主要靠jar包应用:第三方开发一个工具包,放在中心仓库中(maven, gradle), 使用者从其他信息渠道(csdn, stackoverflow等等)根据问题定位到这个jar包,然后在代码工程中引用。理论上,如果这个第三方jar包很稳定(例如c3p0),那么该jar包的维护者就很少甚至几乎不会和使用者建立联系。如果某些中间件开发者觉得不满足自己公司/部门的需求,会根据该jar包再做一次自定义封装。

纵观上述整个过程,不难发现两点:

  1. 工具包开发者和使用者没有建立稳定的协同渠道

  2. 工具包开发者对自己成品的发展掌控很薄弱

 那么如果有人想要建立一套标准呢?比如log标准,比如数据库连接标准,那么只能有几个大公司联盟,或者著名的开发团队联盟,制定一个标准,并实现其中核心链路部分。至于为什么不实现全部链路,原因也很简单:软件领域的协同本身就是弱中心化的 ,否则你不带别人玩,别人也不会采用你的标准(参考当年IBM推广的COBOL)。

综上而言:委派模式是基于当前软件领域的协作特性,采取的较好的软件结构模式。

 

图片

 

所以啥时候采用委派模式呢?

  • 存在设定某个标准并由中心化团队负责的必要

  • 使用者有强烈的需求自定制某些局部实现

这里就举一个硬件领域的反例:快充标准。在2018年甚至更早,消费者就需要一个快充的功能。但是快充需要定制很多硬件才能实现,所以此时就具备了条件一,但是当时并没有任何一个团队或者公司能够掌控安卓手机硬件整个生态,无法共同推出一个中心化团队去负责,从而导致各个手机厂商的快充功能百花齐放:A公司的快充线,无法给B公司的手机快充。

3.2 什么是委派模式?

基于上述

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇String详解 下一篇读Java8函数式编程笔记06_Lambda..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目