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 依赖

        
        
        <dependency> <!-- 绑定:告诉Slf4j使用Log4j2 -->
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>${log4j2.version}</version>
        </dependency>
        <dependency> <!-- 绑定:告诉commons logging使用Log4j2 -->
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-jcl</artifactId>
            <version>${log4j2.version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>${log4j2.version}</version>
        </dependency>

        <dependency><!--核心实现-->
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>${log4j2.version}</version>
        </dependency>
        
        <dependency><!-- 必选api -->
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>   

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容