java日志的组件

前言

最近想系统学习一下spring框架的知识,搭完框架运行第一个 HelloWorld 的例子后。我发现要查看 spring 启动流程需要查

看启动日志。以前使用的时候都是照抄网上的配置使用,不知道到底是怎么工作的。后来上网查了一下,发现 Java 日志

组件居然有好几种:

  • logging (JDK14提供) 被强大的三方日志组件给埋没
  • log4j(Apache的开源项目log4j)
  • log4j2(log4j的重构,提升性能,具体参见log4j2改善)
  • logback(和log4j对比)
  • common-logging (通用的日志接口,动态加载绑定)
  • slf4j(通用的日志接口,编译静态加载绑定)

上面说了4种日志实现和两种通用接口.对于这么多日志框架,和一大堆maven下面的依赖包。我们应该怎么选择呢?

common-logging(动态接口)

common-logging 是apache提供的一个通用的日志接口。用户可以自由选择第三方的日志

组件作为具体实现,像log4j

或者JDK自带的loggingcommon-logging会通过动态查找的机制,在程序运行时

自动找出真正使用的日志库。当然,

common-logging内部有一个simple logger的简单实现,但是功能很弱。所以使用

common-logging,通常都是配合着

log4j来使用。使用它的好处就是,代码依赖是common-logging而非log4j, 避免了和具体

的日志方案直接耦合,在有必要时,可以更改日志实现的第三方库。

longging使用代码

import org.apache.commons.logging.Log;  
import org.apache.commons.logging.LogFactory;  
  
public class A {  
    private static Log logger = LogFactory.getLog(this.getClass());  
}  

spring-core默认使用的就是common-logging.该通用接口默认有以下实现 (不支持logback)

动态查找原理:

Log 是一个接口声明。LogFactory 的内部会去装载具体的日志系统,并获得

  1. 实现该Log 接口的实现类。LogFactory 内部装载日志系统的流程如下:

  2. 首先,寻找org.apache.commons.logging.LogFactory 属性配置。

  3. 否则,利用JDK1.3 开始提供的 service 发现机制,会扫描 classpah 下的METAINF/services/org.apache.commons.logging.LogFactory文件,若找到则装载里面的配置,使用里面
    的配置。

  4. 否则,从Classpath 里寻找commons-logging.properties ,找到则根据里面的配置加载。

  5. 否则,使用默认的配置:如果能找到 Log4j 则默认使用 Log4j 实现,如果没有则使 JDK14Logge 实现,再没有则使

    commons-logging 内部提供的 SimpleLog 实现。

common-logging转向某个日志框架

    commons-logging.jar         核心API(必选)
    log4j-jcl.jar               绑定使用lo4j1(可选)
    jcl-over-slf4j.jar          绑定使用slf4j(可选)  接口到接口 - -

slf4j(静态接口)

common-logging通过动态查找的机制,因此在不同classloader的情况下可能无法正常工作,所以就有slf4j这种编译时静态

绑定的框架。

slf4j是Java简单日志门面,类似JDBCDriver,需要不同的日志框架提供实现才能正常工作

slf4j使用代码

import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
  
public class A {  
    private static Log logger = LogFactory.getLog(this.getClass());  
}  

slf4j转向某个实际日志框架

    slf4j-api.jar               核心接口(必选)
    slf4j-log4j12.jar           绑定使用log4j1(可选)
    slf4j-jdk14.jar             绑定使用jdk-logging(可选)
    logback-classic.jar         绑定使用logback(可选)
    log4j-slf4j-impl.jar        绑定使用log4j2(可选)
    slf4j-jcl.jar               绑定使用commons-logging(可选) 接口又到了一个接口- -!

某日志框架转向slf4j###

比如spring-core内部使用的是common-logging接口。Google AppEngine 它使用的是 java.util.logging(JUL)这个时候

需要使用到桥接器,所谓的桥接器就是一个假的日志实现工具,比如当你把 jcl-over-slf4j.jar 放到 CLASS_PATH 时,即使某

个组件原本是通过 JCL 输出日志的,现在却会被 jcl-over-slf4j “骗到” slf4j 里,然后 slf4j 又会根据绑定器把日志交给

具体的日志实现工具

    log4j-over-slf4j.jar        log4j转向slf4j
    jcl-over-slf4j.jar          common-logging转向slf4j
    jul-to-slf4j.jar            jdk-logging转向slf4j

tip:这里值得注意的是当你使用log4j-over-slf4j.jar -> slf4j-api.jar -> log4j-core.jar时就会把日志踢来踢去进入死循环中

总结

java中繁多的日志框架和依赖包让人摸不着头脑,本文理清日志组件的相关历史和使用。在今后的项目中遇到日志依赖问题

也能够很好的解决。目前来说日志框架的典型搭配是

    slf4j-api.jar               slf4j 核心api
    jcl-over-slf4j.jar          common-logging桥接器
    jul-to-slf4j.jar            jdk-logging桥接器(如果项目中没有jdk-logging的日志可以不选用)
    log4j-slf4j-impl.jar        绑定log4j2
    log4j-core.jar              log4j真正实现
    log4j-api.jar               log4japi

附上相关maven 依赖

        
        
         
            org.apache.logging.log4j
            log4j-slf4j-impl
            ${log4j2.version}
        
         
            org.apache.logging.log4j
            log4j-jcl
            ${log4j2.version}
        
        
        
            org.apache.logging.log4j
            log4j-api
            ${log4j2.version}
        

        
            org.apache.logging.log4j
            log4j-core
            ${log4j2.version}
        
        
        
            org.slf4j
            slf4j-api
            1.7.21
           

最终效果就是..编程 API 使用的是 slf4j 而最终实现打印的是 log4j ,这样一来项目只需要配置 log4j2.xml , 如果需要转换某

种实现,只需要根据相关规则修改依赖包,不需要修改代码,因为是针对接口slf4j实现的

你可能感兴趣的:(java日志的组件)