日志对于项目的重要性不言而喻,而成熟的日志框架较多,包括:Log4j,Log4j2,Slf4j,LogBack等等。Slf4j (simple logging façade for Java)以外观模式【1】为我们提供了一个对各种日志框架的简单抽象。Slf4j允许用户在部署阶段将需要的日志框架以plugin的形式提供给系统。
Slf4j的基本用法
Slf4j的配置非常简单,首先从其官网下载jar包并将其放入外部依赖:slf4j-api-$version.jar
新建一个类:
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
运行这段代码的时候,会遇到警告信息:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
这是因为程序在classpath里面找不到slf4j的binding。正像前面所说的,Slf4j支持多种日志框架,你可以在官方网站【2】上下载相应的jar包。Slf4j采用了经典的bridge设计模式实现了这样特性。文章后面将简单介绍bridge模式。Slf4j的优势在于,在不同的日志框架之间进行的切换是在部署阶段完成的,也就是说,只需要替换对应的jar包,不需要修改任何代码。
Plug in Log4j
目前,市面上较为常用的组合是slf4j+log4j,我们就以此为例:
在class path中加入slf4j-log4j12-$version.jar
/src/main/resources下新建文件:log4j.properties
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
再次运行代码,
0 [main] INFO HelloWorld - Hello World
Plug in其他日志框架
slf4j还支持其他多种日志框架:
concrete-bindings.png
Adapter 支持
此外,如果你的应用部署的是log4j而不是slf4j,但是需要将日志转发至slf4j,也可以部署相应的adapter【3】。
Bridge(桥接)模式
Bridge作为一种structural设计模式【4】,将抽象和实现分开,是一种将接口类的实现类封装起来的机制。
Bridge设计模式下,可以分别开发抽象部分和实现部分,客户代码只能访问抽象部分,而不用关心实现部分。
抽象部分是一个接口或抽象类,实现部分也是一个借口或抽象类。抽象部分包含一个到实现部分的索引。抽象部分的子类作为一个“refined abstraction”,而实现部分的子类是一个concrete实现。我们能在运行时改变实现部分,因为我们可以在抽象部分中改变对实现部分的引用,从而使得对实现部分的改变并不影响客户端代码。也就是说,bridge设计模式使得抽象部分和实现部分松耦合。
bridge.png
如上图所示,
- Abstraction:bridge设计模式的核心,定义了需要解决的问题。他包含一个对实现部分的引用。
- Refined Abstraction:扩展了抽象部分,负责“refined”的功能,并对实现部分隐藏了refined的功能。
- Implementer:为实现部分定义了接口,其功能不一定要和抽象部分对外提供的功能一致。实现部分仅仅是以接口的形式提供了抽象部分所需要的操作。
- Concrete Implementation:为实现部分提供了具体的方法。
Bridge的设计模式是古老的建议的具体应用:“prefer composition over inheritance”。这种模式可以在运行时绑定实现,主要用于实现独立于平台的特性。
Adapter(适配器)模式
适配器模式【5】【6】将一个类的接口适配成用户所期待的。一个适配器通常允许因为接口不兼容而不能一起工作的类能够在一起工作,做法是将类自己的接口包裹在一个已存在的类中。
Adapter 设计模式主要目的组合两个不相干类,常用有两种方法,第一种解决方案是修改各自类的接口。但是如果没有源码,或者不愿意为了一个应用而修改各自的接口,则需要使用 Adapter 适配器,在两种接口之间创建一个混合接口。
Adapter.png
如图所示是适配器模式的类图。Adapter 适配器设计模式中有 3 个重要角色:被适配者 Adaptee,适配器 Adapter 和目标对象 Target。其中两个现存的想要组合到一起的类分别是被适配者 Adaptee 和目标对象 Target 角色,按照类图所示,我们需要创建一个适配器 Adapter 将其组合在一起。
适配器应用场景:
- 当我们需要外部组件的功能,但是他和客户端期待的接口并不兼容的时候,
- 当我们需要重用应用的既有代码,又不想或不能在原始代码上进行修改的时候。
【1】外观模式
【2】www.slf4j.org
【3】log4j-to-slf4j
【4】桥接模式
【5】适配器模式1
【6】适配器模式2
网友评论