由sl4j门面的实现引发的联想

1 篇文章 0 订阅

sl4j的门面模式

使用sl4j门面模式,有个很好的特性:一套代码到处运行

现象:只要使用

// 引入sl4j类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// 定义LOGGER
public static final Logger LOGGER = LoggerFactory.getLogger(类.class);

// 使用LOGGER
LOGGER.info("------info日志---------");

无论项目中使用的logback还是log4j2,用户都不需要关心。

所以阿里编程规范里也规定:

应用中不可直接使用日志系统( Log4j、 Logback) 中的 API,而应依赖使用日志框架

( SLF4J、 JCL–Jakarta Commons Logging) 中的 API,使用门面模式的日志框架,有利于维护和

各个类的日志处理方式统一。

那sl4j-api在不知道项目引用哪种日志框架的时候,是如何调用项目中的日志框架的呢。

简单来说就是:

  1. 项目中添加了一个sl4j-日志框架的“转接头”包。
  2. 在转接头包里定义一个固定类。
  3. sl4j-api调用这个固定的类。

下面就引出本文的一个联想主题。。。

如何调用一个“还不存在”的类

下面是我的总结:
在这里插入图片描述

主要分为两类:框架开发和日常应用。我们多数人,其实只要关心下半部分就可以。
一图胜千言,就不多讲了。上图中SpringBoot自动装配的内容,可以看我的另一篇博客SpringBoot自动装配串讲

我们重点说一下本文的主角sl4j。sl4j-api直接调用的一个“未知的类”。看一下源码:

请添加图片描述

以logback为例,看一下这个类实际的位置所在,在logback-classic里:

在这里插入图片描述

sl4j要解决的两个困难

  1. sl4j-api要调用一个不存在的类。那么sl4j-api在开发阶段,项目工程里肯定要有一个临时的实现类可以被调用。然后开发完,打成jar包之后,还要把这个临时的类删除掉。否则就没法调用被用户引入的其他包里的类了。那怎么删除临时类,然后重新打包呢?下面是操作流程:

    • 解压缩jar文件。可以使用以下命令解压缩jar文件:jar -xf yourjarfile.jar,其中"yourjarfile.jar"是你要解压缩的jar文件的名称。

    • 进入解压后的文件夹,找到你想要删除的类所在的文件夹。删除该类的.class文件。

    • 在解压后的文件夹中重新打包jar文件。你可以使用以下命令重新打包jar文件:jar -cf yourjarfile.jar *,其中"yourjarfile.jar"是你要重新打包的jar文件的名称(这里的星号表示打包当前目录中的所有文件及文件夹)。

  2. sl4j-api直接调用类的静态方法,如果被调用的类不存在,那肯定是会报错的。如何在调用之前判断一下用户有没有引入正确的包呢?朴素的想法就是在项目里找找有没有这样的类。如果没有,则直接结束程序。如果引入了多个(比如同时引入里logback和log4j)也提醒一下用户(jvm会随机挑一个执行)。那怎么找class文件呢?

    ClassLoader.getResources(一个classLoader类里找class文件的方法,有静态的方法,也有非静态的方法)。

ClassLoader.getResources

这个方法可以传入一个确定的全类名,在classpath里找找到这个class文件。sl4j就是这么做的,看下图:

在这里插入图片描述

如果用户引用了两个实现类,那么上图中的paths就会获取到两个。后面就会通过日志告诉用户这个问题(但并不影响使用,jvm会随机挑一个执行)

也可以传入一个path目录,找目录下的所有class。Spring在扫描包下的所有类时,用的就是这个方法,看下图:

在这里插入图片描述

:既然Spring是个容器,可以从自己的容器里根据接口找对象。那么ClassLoader也可以视为一个容器(一个装类的容器)。那么为什么没有类似Spring的getBeansOfType方法?
因为:JVM是“懒加载”,只有在第一次使用时,才会加载对应的类。 即使是Spring的getBeansOfType也不能保证获取到所有接口的实现类,Java更不会提供这种不确定的方法了。

感想

为什么sl4j要用门面模式?
为什么日志类的包那么乱?
log这么基础常用,而且看起来也不复杂的东西,jdk为什么没能统一接口?

看过java日志类的历史,感觉:
初看是因为:sun公司没有远见和能力,Apache内部人心不齐,才导致日志框架混乱不堪。
深入想想:日志其实是一个很偏应用的模块。看似简单基础,但要一下子做的尽善尽美并不容易,需要经历很多年的项目积累。以至于sun公司和Apache都无法一下子把握住。

2021年年末,暴雷log4j2出现“核弹级漏洞”。
直接原因:log4j2中使用了JNDI技术,然后没把握住,出现了漏洞。
个人感觉:纯粹多此一举。JNDI这么危险的技术应用在日志中,但多数人听都没听说过。
软件需要足够丰富的功能,但也不要太越界,什么功能都加。尤其像日志框架这种很纯粹的软件,在满足基本功能的同时,尽量简单。

参考

Logback源码分析
源码详解系列(七) ------ 全面讲解logback的使用和源码
从0到1带你深入理解log4j2漏洞

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值