SLF4J
java世界的日志框架太多了, Jakarta Commons Logging (JCL)
, java.util.logging (jul), Log4j, Logback等等. 其中 log4j和logback是同一个作者写的, 这个作者为了统一日志的API, 又创作了SLF4J, SLF4J采用门面模式定义了日志操作的API, 但是并没有提供实现,
具体的实现由用户引入的jar包决定, 比如Log4j或者Logback等.
为了能让之前的项目, 比如一个比较古老的项目使用了 JCL, 也能使用SLF4J
带来的好处(接口和实现分离), 就出现了桥接的需求.

一旦桥接到了SLF4J
, 底层的日志实现就可以随便选了.
使用
这里拿JCL
为例, 介绍下如何使用桥接包.
- exclude掉
JCL
对应的jar包
- 引入
jcl-over-slf4j
比如拿spring mvc
为例, 他内部使用的是JCL
作为日志实现, 我们需要做的就是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency>
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${sl4j.version}</version> </dependency>
<dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.25</version> </dependency>
|
实现原理
桥接的实现原理就是不引入JCL
等之前包的实现, 在桥接的jar包中实现一套相同的api.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| ➜ jcl-over-slf4j-1.7.25-sources tree . ├── META-INF │ ├── MANIFEST.MF │ └── services │ └── org.apache.commons.logging.LogFactory └── org └── apache └── commons └── logging ├── impl │ ├── NoOpLog.java │ ├── package.html │ ├── SimpleLog.java │ ├── SLF4JLocationAwareLog.java │ ├── SLF4JLogFactory.java │ └── SLF4JLog.java ├── LogConfigurationException.java ├── LogFactory.java ├── Log.java └── package.html
|
在LogFactory
中使用的是SLF4JLogFactory
来获取Logger
, 最终用到的是slf4j-api
中定义的方法.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| static LogFactory logFactory = new SLF4JLogFactory();
public Log getInstance(String name) throws LogConfigurationException { Log instance = loggerMap.get(name); if (instance != null) { return instance; } else { Log newInstance; Logger slf4jLogger = LoggerFactory.getLogger(name); if (slf4jLogger instanceof LocationAwareLogger) { newInstance = new SLF4JLocationAwareLog((LocationAwareLogger) slf4jLogger); } else { newInstance = new SLF4JLog(slf4jLogger); } Log oldInstance = loggerMap.putIfAbsent(name, newInstance); return oldInstance == null ? newInstance : oldInstance; } }
|
参考