一、Log4j
Log4j是一个Java日志框架,使用Log4j可以对日志等级、日志输出地(文件或网络等)、日志输出格式各方面作出有效的管理。
Log4j的结构并不复杂,主要使用了策略模式。
每个Logger有多个Appender,Appender决定写日志的策略。
Appender持有Layout引用,Layout决定日志格式。
类图结构如下:
单纯使用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则提供相应的绑定类,如下图:
而LoggerFactory则直接使用该类获取ILoggerFactory:
如果要切换其他的日志实现,则替换掉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。