slf4j-api、slf4j-log4j12、log4j之间关系

1. slf4j-api

slf4j:Simple Logging Facade for Java,为java提供的简单日志Facade。Facade门面,更底层一点说就是接口。它允许用户以自己的喜好,在工程中通过slf4j接入不同的日志系统。

因此slf4j入口就是众多接口的集合,它不负责具体的日志实现,只在编译时负责寻找合适的日志系统进行绑定。具体有哪些接口,全部都定义在slf4j-api中。查看slf4j-api源码就可以发现,里面除了public final class LoggerFactory类之外,都是接口定义。因此slf4j-api本质就是一个接口定义。

它只提供一个核心slf4j api(就是slf4j-api.jar包),这个包只有日志的接口,并没有实现,所以如果要使用就得再给它提供一个实现了些接口的日志包,比 如:log4j,common logging,jdk log日志实现包等,但是这些日志实现又不能通过接口直接调用,实现上他们根本就和slf4j-api不一致,因此slf4j又增加了一层来转换各日志实 现包的使用,比如slf4j-log4j12等。

slf4j+log4j组合使用模式:
1. slf4j-api-1.5.11.jar
2. slf4j-log4j12-1.5.11.jar
3. log4j-1.2.15.jar
4. log4j.properties(也可以是 log4j.xml)

具体使用日志类的API:

1. log4j:
import org.apache.log4j.Logger;
Logger logger= Logger.getLogger(xx.class);
 
2. slf4j+log4j:(推荐)
import  org.slf4j.Logger;
import  org.slf4j.LoggerFactory;
Logger logger = LoggerFactory.getLogger(xx.class);

 

2. slf4j-api、slf4j-log4j12、log4j

下图比较清晰的描述了它们之间的关系,例子为当系统采用log4j作为日志框架实现的调用关系:

1. 首先系统包含slf4j-api作为日志接入的接口:编译时slf4j-api中public final class LoggerFactor类中private final static void bind()方法会寻找具体的日志实现类绑定,主要通过StaticLoggerBinder.getSingleton()的语句调用。
2. slf4j-log4j12是链接slf4j-api和log4j中间的适配器:它实现了slf4j-api中StaticLoggerBinder接口,从而使得在编译时绑定的是slf4j-log4j12的getSingleton()方法。
3. log4j是具体的日志系统:通过slf4j-log4j12初始化Log4j,达到最终日志的输出。

3.1 log4j的使用

1:
slf4j提供的是接口。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

 

2: 只接使用log4j
引入 <dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggerFactory;

import org.apache.log4j.Logger;
Logger logger= Logger.getLogger(xx.class);

3.3.1:使用log4j api 与log4j-core
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.13.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.13.3</version>
</dependency>
获取Logger实例:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

获取Logger方法:
Logger Logger = LogManager.getLogger();

Logger实列:
org.apache.logging.log4j.core.Logger

实现原理: 通过SPI机制定义配置具体的 log4j2.component.properties 找到具体的 log4j2.loggerContextFactory

还可以通过ServiceLoader  来找到具体的Log4jContextFactory . 

org.apache.logging.log4j.spi.Provider

public class Log4jProvider extends Provider {
public Log4jProvider() {
super(10, "2.6.0", Log4jContextFactory.class);
}
}

Log4jContextFactory 管理一组 Log4jContext 
Log4jContext  管理一组 logger.

3.3.2 slf4j+log4j:如何使用
如下配置会报
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.13.3</version>
</dependency>

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation

应该依赖,实会将api, 与log4j都依赖了

 

 

 

 因为都是api , 还没有真正的实现, 还需要引入core

 

 如下依赖,将是最好的依赖方式。


<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>

 

 

log4j-slf4j-impl 是如何做桥接的:

org.apache.logging.slf4j。Log4jLogger 是 org.slf4j.Logger的实现

其中包含了。
private transient ExtendedLogger logger; 

org.apache.logging.log4j.core.Logger 是 org.apache.logging.log4j.Logger的一种实现。


org.apache.logging.slf4j。Log4jLogger 会对Logger进行包装。

org.slf4j.impl.StaticLoggerBinder; 是桥接的工具。





 

posted @ 2021-07-21 11:08  风云快客  阅读(675)  评论(0编辑  收藏  举报