在工程项目中,会遇到许多不同的日志jar包,例如:log4j、logback、log4j2等等,但每个操作的方式不相同,slf4j统一了不同日志实现的接口,即Facade mode。
门面模式(Facade mode)
内部子系统存在很多类,客户端往往需要和很多对象进行访问,比较复杂。现在我们有一个门面(Facade),对外隐藏了系统的复杂性,并向客户端提供了可以访问的接口,门面模式的好处是将客户端和子系统松耦合,方便子系统的扩展和维护。
- 门面(Facade)角色 :客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
- 子系统(SubSystem)角色 :可以同时有一个或者多个子系统。每个子系统都不是一个单独的类,而是一个类的集合。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。
门面模式与迪米特法则:迪米特法则(一个对象应该对其他对象保持最少的了解),门面模式降低了类与类之间的耦合。
slf4j
slf4j门面,不管日志组件使用的是log4j还是logback等等,对用调用方的我们并不需要知道使用的具体日志组件,升级或者实现的更换,调用方都不需要改变。slf4j-xxx.jar就是中间的适配。
首先使用静态工厂来获取Logger对象,传入的class,最终会转化为name,每个类的日志处理可能不同,所以根据传入类的名字来判断类的实现方式
主要方法有bind()
,首先获取实现日志的加载路径,检查路径是否合法,然后初始化StaticLoggerBinder的对象,寻找合适的实现方式使用。
类加载器加载类,寻找StaticLoggerBinder.class文件,实现了这个类的日志组件,就可以被使用,可能有多个实现该类的日志组件(引入了多个日志包),那么谁先加载,就使用谁。
统一日志
如果应用中引入了许多不同的框架,不同的框架有着自己不同的日志实现,有的时候需要统一日志标准,底层使用一个日志实现。
如左上角,假如引入Spring框架,它是引用Apache的commons-logging。
现在的需求是:项目需要统一使用slf4j的api、底层为logback的实现。
移除commons-logging的依赖,可是Spring框架此时因为缺少jcl的依赖会报错
引入jcl-over-slf4j.jar包去代替jcl。
底层日志实现slf4j
SpringBoot里已经引入了其它日志的桥接转换包,因此SpringBoot应用中,直接移除不需要的日志框架依赖,换成了slf4j+logback。