0%

日志与门面模式

在工程项目中,会遇到许多不同的日志jar包,例如:log4j、logback、log4j2等等,但每个操作的方式不相同,slf4j统一了不同日志实现的接口,即Facade mode。

门面模式(Facade mode)

内部子系统存在很多类,客户端往往需要和很多对象进行访问,比较复杂。现在我们有一个门面(Facade),对外隐藏了系统的复杂性,并向客户端提供了可以访问的接口,门面模式的好处是将客户端和子系统松耦合,方便子系统的扩展和维护。

  • 门面(Facade)角色 :客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
  • 子系统(SubSystem)角色 :可以同时有一个或者多个子系统。每个子系统都不是一个单独的类,而是一个类的集合。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。

门面模式与迪米特法则:迪米特法则(一个对象应该对其他对象保持最少的了解),门面模式降低了类与类之间的耦合。

slf4j

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。

参考

阿里Java开发手册思考(三)
《JAVA与模式》之门面模式