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:
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; 是桥接的工具。