参与项目的同学大多都知道,日志是多么的重要。日志能帮我们定位问题,也可以通过日志去统计分析数据。而我们手动去搭建日志框架稍显繁琐,所以springboot 都为我们准备好了当下成熟的日志框架。
1、当下日志框架的介绍
日志-抽象层 | 日志-实现层 |
JCL、SLF4J、jboss-logging | jul、log4j、log4j2、logback |
目前常用的日志框架组合就是 SLF4J(抽象层) + logback (实现层);而springboot 默认使用的日志框的也就是 SLF4J + logback;
使用 SLF4J + logback 的组合其实是当下的最优解, SLF4J , log4j , logback 它们其实同一个人的杰作,相对兼容性会好很多;目前像 log4j 是存在性能问题, jul 、 log4j2 对于 SLF4J 兼容相对弱一些。
2、SLF4J 介绍
slf4j 已知是抽象层 ,它是日志实现层的适配器,通过slf4j你是可以调用所有日志实现层的,slf4j 官网出图,如下:
我们可很清晰的看到 slf4j 是如何实现对于实现层的调用的。
对于 slf4j 如何使用,官网也给了一个HelloWorld demo,如下:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// 咋样,是不是有熟悉感,是不是经常用
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
3、 SLF4J 如何在项目中使用同一的实现层
因为java日志历史遗留问题,导致日志的实现层是没有一个统一的标准的,所以大家使用的spring、hibernate、mybatis 等框架使用的不是一套日志实现层,如 spring 使用的commons-logging(新版本的spring使用的spring-jcl,原理还是改了 commons-logging 的实现,改成 SLF4J )、 hibernate 使用的是jboss-logging。那么我们怎么使用SLF4J把整个项目使用一个实现层呢?
SLF4J 给我们出了一个狸猫换太子的方案,看下图:
SLF4J 很鸡贼啊,他偷偷的将 jul、log4j、log4j2 这些实现层源码都改掉了,出了对应的包,当项目中框架使用到 commons-logging 时,commons-logging 会被排除掉,增加 jcl-over-slf4j.jar 的依赖,大事就成了, jcl-over-slf4j.jar 其实就是涵盖了 commons-logging 的源码,只是在调用日志是,用了 SLF4J 的方法;鸡贼不。springboot默认的日志框架也是基于这一套理论。
说明:spring 新版本中自己偷梁换柱 ,整了个 spring-jcl ;这个东西和 jcl-over-slf4j.jar 原理是一样的;
我们可以看下 spring-jcl.jar 的实现;看下包下 LogFactory类
/**
* Convenience method to return a named logger.
* @param name logical name of the <code>Log</code> instance to be returned
*/
public static Log getLog(String name) {
return LogAdapter.createLog(name);
}
LogAdapter.createLog(name)
点过去看到的代码是
public static Log createLog(String name) {
switch (logApi) {
case LOG4J:
return Log4jAdapter.createLog(name);
case SLF4J_LAL:
return Slf4jAdapter.createLocationAwareLog(name);
case SLF4J:
return Slf4jAdapter.createLog(name);
default:
// Defensively use lazy-initializing adapter class here as well since the
// java.logging module is not present by default on JDK 9. We are requiring
// its presence if neither Log4j nor SLF4J is available; however, in the
// case of Log4j or SLF4J, we are trying to prevent early initialization
// of the JavaUtilLog adapter - e.g. by a JVM in debug mode - when eagerly
// trying to parse the bytecode for all the cases of this switch clause.
return JavaUtilAdapter.createLog(name);
}
}
哈哈,最后还是到了SLF4J的去适配最终的实现层。
4、springboot 的日志框架介绍
目前我用的springboot 2.2.2.RELEASE版本;基于这个版本,做一下介绍。
当前这个版本spring已经更新到5.2.2.RELEASE 版本; spring 自己底层 commons-logging.jar 的应用已经被替换成了spring-jcl。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jcl</artifactId>
<version>5.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
spring-jcl 的实现原理上面也提到过,基于 commons-logging.jar 的源码结合slf4j实现的封装。
springboot 默认的日志框架还是 slf4j + logback;
slf4j 的替换方案除了少了 jcl-over-slf4j.jar ,其他依旧健在。
springboot 日志框架变成了
全部评论