一、Log4j

Log4j是一个Java日志框架,使用Log4j可以对日志等级、日志输出地(文件或网络等)、日志输出格式各方面作出有效的管理。

Log4j的结构并不复杂,主要使用了策略模式。

每个Logger有多个Appender,Appender决定写日志的策略。

Appender持有Layout引用,Layout决定日志格式。

类图结构如下:

slf4j、apache common logging、log4j、logback关系比较

单纯使用Log4j框架,代码如下所示:

package org.lin.dog;

import org.apache.log4j.Logger;

public class App {
	
	private static final Logger logger = Logger.getLogger(App.class);
	
	public static void main(String[] args) {
		logger.info("hello world");
	}
}

 

 

二、Apache Common Logging

也称为Jakarta Commons Logging(JCL),他提供了日志接口,但不提供接口实现。

JCL的原理是在运行时,动态查找日志框架实现,并为具体的日志框架实现提供适配器,将其转为JCL的接口。于是程序中可以统一使用JCL接口,并轻松切换日志框架实现。

查找的过程:

1.首先获取LogFactory实例,如果没有配置,默认使用LogFactoryImpl

2.LogFactoryImpl中,查找日志框架的过程为:

1)查找用户定义的LoggerAdaptor,使用ContextClassLoader加载LoggerAdaptor

2)查找Log4j

3)查找Jdk14Logger

4) SimpleLog,简单输出到控制台

Apache Common Logging由于是在运行时动态查找并加载日志框架实现,一般情况下使用ContextClassLoader加载Logger,也因为这个特性,在OSGI模式下,JCL无法正常工作,因为每个模块有自己的类加载器。

使用JCL,代码如下所示:

package org.lin.app1;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Cat {
	private static final Log log = LogFactory.getLog(Cat.class);
	
	public static void main(String[] args) {
		log.info("hello");
	}
}

三、slf4j

SLF4J,即简单日志门面(Simple Logging Facade for Java),和JCL类似,但是slf4j加载具体日志框架的方式和JCL不同。

SLF4J要求具体的日志框架提供相应的Jar包,用于绑定到该框架。

如slf4j和log4j结合使用时,需要如下两个依赖:

  	<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
	<dependency>
	    <groupId>org.slf4j</groupId>
	    <artifactId>slf4j-api</artifactId>
	    <version>1.7.25</version>
	</dependency>
  	<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
	<dependency>
	    <groupId>org.slf4j</groupId>
	    <artifactId>slf4j-log4j12</artifactId>
	    <version>1.7.25</version>
	</dependency>

其中slf4j-api 提供基本的日志接口,slf4j-log4j12则提供相应的绑定类,如下图:

slf4j、apache common logging、log4j、logback关系比较

而LoggerFactory则直接使用该类获取ILoggerFactory:

slf4j、apache common logging、log4j、logback关系比较

如果要切换其他的日志实现,则替换掉slf4j-log4j12的jar包即可。

如果已经使用了JCL,又想切换到slf4j,怎么办?

其实也很简单,添加如下依赖,并去掉JCL原本的依赖:

<!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>1.7.25</version>
</dependency>

原理很简单,重新实现了JCL的接口,改为简单调用sl4j。此时日志调用的流程是:

jcl -> slf4j -> log4j

这样子,就可以继续使用原本的JCL接口,轻松切换到slf4j了。

最后,使用slf4j的接口,代码如下:

package org.lin.dog;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App {
	
	private static final Logger logger = LoggerFactory.getLogger(App.class);
	
	public static void main(String[] args) {
		logger.info("hello world");
	}
}

四、logback

logback实际上是log4j的升级版,包含三个模块:logback-core、logback-classic、logback-access。

其中logback-core、和logback-classic结合,构成一个完整的日志框架,架构类似log4j,但是在性能上有显著的提升。并且,logback-claasic提供了对slf4j的支持,因此logback天生支持slf4j。

相关文章: