1. Java有哪些跟日志相关的名词 ?他们有什么关系 ?为什么出现了这么多日志相关的技术 ?
说到Java的日志,相信很多人,都是很懵的,比如:log4j,slf4j,logback,还有spring的日志体系等等。
是不是感觉日志太多了,不知道他们具体是做什么的,只知道可以打印日志。现在就说一下日志,先说日志相关的名词。
jul : jdk提供的日志打印,在jdk3的时候,java为了可以打印日志,就提供了jul,因为在java.util.logging包下,所以简称为jul ,jul大概在jdk4以后就没有再更新了,所以很多人没有听过,但是实际工作中,可能你用到了,但是你不知道而已。
log4j :log4j出现在jul之后的日志打印,因为jul没有更新了,并且是jdk提供的,源码不可更改,所以输出的日志格式固定,有些需要的关键信息打印不出来,所以出现了log4j。
log4j2 :日志打印技术。
jcl :Apache提供的日志平台 2014年之后就没有更新过了。不提供打印功能,在 org.apache.commons.logging包下,maven引入commons-logging包。因为有了jul 和 log4j两种日志打印技术,所以为了程序员使用的方便,jcl就开发了一个平台,可以自动选择 到底是使用 jul 还是 log4j 的日志实现,就算是没有依赖log4j的jar包,因为jul是jdk提供的,所以使用 jcl就可以直接使用jul技术作为日志打印。
slf4j :也是日志平台。因为jcl没有更新以后就出现了 slf4j,并且jcl有个缺点:就是只能使用log4j 和 jul两种日志打印技术。所以slf4j 规避了上面的缺点,新增绑定功能,并且还新增了一个桥接技术。因为slf4j是日志平台,所以使用slf4j的话,就需要绑定一个日志打印技术。 绑定功能比如:直接导入一个 slf4j-jdk14 的依赖(就相当于把jdk4提供的jul的日志打印技术,绑定到slf4j的日志平台上,然后直接使用slf4j的代码,就可以记录日志了。)桥接技术比如:一个项目中,使用了很多种日志技术,现在项目要求,只是用log4j技术打印,但是现在项目中又有,jul 和 logback 两种日志打印,就使用桥接技术,把jul 和 logback的打印功能,交给slf4j,然后slf4j再通过绑定技术,把日志打印权,最终交给log4j. (这样就规避了jcl 代码固定,且不抽象的缺点)
logback :日志打印技术(目前最新的日志打印技术)。
spring-jcl (spring5自主研发):spring的日志平台(spring-context包下),和jcl 有异曲同工之处,上面说了jcl没有更新后,spring就开始继续jcl的功能扩展(名字叫spring-jcl),可以整合的日志打印技术更多。
spring4用的是jcl技术,所以引入log4j的时候,直接就使用了log4j打印spring启动日志。
但是spring5,修改了jcl技术,独立开发出了spring-jcl,所以在使用log4j的时候,并没有使用,而是使用了jul日志打印技术。
为什么?
因为源码switch case中,没有log4j的选项,只有log4j2,默认使用的是JavaUtilsLog(JUL日志打印)
那怎么使用log4j呢 ?
答案:
桥接,绑定
(其实不用使用桥接,因为cash中有slf4j,所以直接绑定要使用的日志技术就可以了)
上面说了这么多,其实使用起来特别简单,就是 引入依赖,调用打印技术特有的方法,就可以实现日志打印。
2. 什么是 Jcl ? 他的作用在源码中,哪里体现 ?
Jcl 是日志平台,本身不提供日志打印的实现,需要引入log4j实现包 或者使用jul包,才能完成日志打印。
代码调用:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public static void main(String[] args) {
Log log = LogFactory.getLog("xxxxx");
log.info("Jcl的日志记录");
}
依赖:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
jcl不直接记录日志,他是一个第三方的工具,在源码中:LogFactoryImpl 类中的771行的方法中 和 843行循环数组判断,是否有
Log4JLogger Jdk14Logger Jdk13LumberjackLogger SimpleLog 这些类,依次来确定使用哪一个日志技术。
3. 什么是Slf4j ,他有什么优点,什么是绑定器,什么是桥接器?
其实上面已经说了,Slf4j不是日志打印技术,Slf4j只是可以整合很多日志打印技术(当前主流的日志打印技术,他都提供了整合)
绑定器的说明:比如一个项目,没有规定具体使用什么日志打印技术,开发人员很随意,有人用log4j,有人用jul,有人用logback,这时候只需要引入相对应的绑定包,将这些技术绑定到slf4j上,然后统一调用slf4j的代码,就可以实现日志日志打印,不需要使用不同的调用方法,看起来怪怪的,但是开发中,一个公司如果有一个架构师,或者统一了日志打印技术,通常是不会出现这种情况,Slf4j就是为了整合日志打印技术而生的。
桥接器的说明:实际开发中,一般也用不到,主要在架构师,构建一个项目的时候,可能考虑使用桥接技术,或者架构师自己开发了一个日志打印技术,然后公司开发的时候,用了这个架构师的日志技术jar包,但是程序员再写代码后,又想使用其他日志技术的时候,才能用到桥接器,说白了,架构师的事情。
4. Slf4j的绑定器去哪里获取 ?
http://www.slf4j.org/manual.html
5. Spring4 与 Spring5的日志特性 与 区别 ?
Spring4 引入log4j的依赖,再编写log4j.properties配置文件,就可以打印log4j的spring启动日志。
Spring5 引入log4j的依赖,和配置文件后,不会打印log4j日志,默认使用JUL日志打印技术,打印启动sping的日志。
6. 如果Slf4j绑定JUL,但是Spring5使用了log4j,项目中要求必须使用JUL,这时候怎么办 ?(slf4j桥接器的使用)
这个问题其实算是对上面知识的重复解析了,这里就直接贴代码吧。
<!-- https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.25</version>
</dependency>
代码调用:
import java.util.logging.Logger;
/**
* @author: wangqinmin
* @date : 2020/5/11
* @description: 仰天大笑出门去,我辈岂是蓬蒿人
*/
public class JulDemo {
public static void main(String[] args) {
Logger logger = Logger.getLogger("xxxxxx");
logger.info("Jul的日志记录....");
}
}
这样就是用桥接技术,去掉了log4j,然后使用绑定技术,最终使用了jul
7. 使用日志的时候,什么情况下,会导致内存溢出 ? (日志使用混乱,桥接导致内存溢出) 举例
比如:桥接了 log4j,然后又绑定了log4j,就会出现内存溢出。
一般在代码混乱的项目中,才会出现这种问题 (比如使用spring,spring某些包下,不仅有slf4j 还有jul,还有log4j,如果这时候对日志体系不熟悉的情况下,胡乱引入桥接的依赖,就会出现内存溢出的情况),或者对各种jar包不了解的情况下,有又运用到了桥接技术的情况下,所以只要不使用桥接技术,就不会出现,使用日志打印出现内存溢出的情况。
不会的可以问我,不懂的可以问我,时间有限,所以没有写各种日志技术的具体使用例子。