基本背景
假如你现在要写一个全新的框架,那这个框架里面必然需要提供一种打印日志的功能。但是业界其实有很多种优秀的日志框架了,你还需要去新写吗?肯定没有必要了。肯定最好选择其中一个就行了,但是日志框架很多,之间的性能差异又不是特别大,固定使用一种也可能不合适。所以需要写一个日志框架,并且这个框架是依赖于已有的框架,但不是固定的。具体的由开发者指定,并且能够由开发者去扩展。那究竟要怎么做呢?从vert.x的日志框架中学习一下。
总述
使用vertx一段时间,其实没有用过它的日志框架,都使用的是slf4j的实现logback。这几天无意中看了一下,我还以为它的日志扩展做了什么特殊处理,实际上什么都没有做,实现其实挺简单的,它把日志的所有实现全部委托给一个日志委托接口,同时自己实现了一些日志框架,比如jullog,log4j,log4j2,slf4j,目前看见实现了这4种。在运行阶段,只能选择其中一个,默认是java的日志框架。并且它采用工厂模式对外提供了一种SPI,允许用户进一步实现其它的日志框架的委托,进而应用在vertx实例中。
整体介绍
4个类的类图,就能够说明白它的设计方案:
先说一下这4个类的职责:
- Logger:日志类,对外暴露的API。内部依赖了一个日志委托对象LogDelegate。所有的操作都由委托对象去执行。同时这个对象本身由日志工厂对象LoggerFactory来创建。
- LoggerFactory:日志工厂对象;用于创建日志对象,内部依赖了一个日志委托工厂的实例,并且是静态的。委托工厂创建被委托对象,
- LogDelegate:日志委托接口;它定义了所有的日志操作方法,它的实现类中可以依赖于具体的日志框架,真正去实现。它由日志委托工厂LogDelegateFactory来创建。
- LogDelegateFactory:日志委托工厂接口;负责创建一个真正的委托对象。
对于开发者来说,vertx提供的获取日志对象的方式和其它的框架是一模一样的
Logger log = LoggerFactory.getLogger(Test.class.getName());
在LoggerFactory类里面依赖了一个日志委托接口LogDelegateFactory,类在加载的时候会初始化,通过一个系统变量来指定这个委托工厂的实现类,然后并实例化。
static {
initialise();
}
public static synchronized void initialise() <