JCL 和 SLF4J

常见的日志实现:JUL、log4j、logback、log4j2
常见的日志门面 :JCL、slf4j
出现顺序 :log4j -->JUL-->JCL--> slf4j --> logback --> log4j2

JCL

JCL简介
全称为Jakarta Commons Logging,是Apache提供的一个通用日志API。
用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的jul, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。
当然,common-logging内部有一个Simple logger的简单实现,但是功能很弱。所以使用common-logging,通常都是配合着log4j以及其他日志框架来使用。
使用它的好处就是,代码依赖是common-logging而非log4j的API, 避免了和具体的日志API直接耦合,在有必要时,可以更改日志实现的第三方库。
JCL 有两个基本的抽象类:
Log:日志记录器
LogFactory:日志工厂(负责创建Log实例)

先导入依赖

<groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
public class JCLTest01 {

    @Test
    public void test01(){

        /*

            我们暂时没有导入第三方的日志框架,例如log4j

            默认的情况下,会使用JUL日志框架做日志的记录操作

            JCL使用原则:
                如果有log4j,优先使用log4j
                如果没有任何第三方日志框架的时候,我们使用的就是JUL

         */
        Log log = LogFactory.getLog(JCLTest01.class);

        log.info("info信息");

    }
}

总结:
    默认情况使用的是JUL,但是在集成了log4j环境后,使用的又是log4j
    通过测试观察,虽然日志框架发生了变化,但是代码完全没有改变

日志门面技术的好处:
    门面技术是面向接口的开发,不再依赖具体的实现类,减少代码的耦合性
    可以根据实际需求,灵活的切换日志框架
    统一的API,方便开发者学习和使用
    统一的配置管理便于项目日志的维护工作

 

SLF4J

简单日志门面(Simple Logging Facade For Java) SLF4J主要是为了给Java日志访问提供一套标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如log4j和logback等。 当然slf4j自己也提供了功能较为简单的实现,但是一般很少用到。对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。所以我们可以得出SLF4J最重要的两个功能就是对于日志框架的绑定以及日志框架的桥接。
官方网站: https://www.slf4j.org/

导入依赖

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>
<!--slf4j 自带的简单日志实现 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.25</version>
</dependency>

SLF4J对日志的级别划分
trace、debug、info、warn、error五个级别
trace:日志追踪信息
debug:日志详细信息
info:日志的关键信息 默认打印级别
warn:日志警告信息
error:日志错误信息

在没有任何其他日志实现框架集成的基础之上
slf4j使用的就是自带的框架slf4j-simple
slf4j-simple也必须以单独依赖的形式导入进来

<!--<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.25</version>
</dependency>-->

    @Test
    public void test03(){
        Logger logger = LoggerFactory.getLogger(SLF4JTest01.class);
        String name = "zs";
        int age = 23;
        //logger.info("学生信息-姓名:"+name+";年龄:"+age);
        //logger.info("学生信息-姓名:{},年龄:{}",new Object[]{name,age});
        logger.info("学生信息-姓名:{},年龄:{}",name,age);

        try {
            int n = 1/0;
        } catch (ClassNotFoundException e) {
            //打印栈追踪信息
            //e.printStackTrace();
            //e是引用类型对象,不能根前面的{}做有效的字符串拼接
            //logger.info("具体错误是:{}",e);//错误写法
            //我们不用加{},直接后面加上异常对象e即可
            logger.info("具体错误是:",e);
        }
    }

SLF4J日志门面,共有3种情况对日志实现进行绑定
1.在没有绑定任何日志实现的基础之上,日志是不能够绑定实现任何功能的
    值得大家注意的是,通过我们刚刚的演示,slf4j-simple是slf4j官方提供的
    使用的时候,也是需要导入依赖,自动绑定到slf4j门面上
    如果不导入,slf4j 核心依赖是不提供任何实现的
2.logback和simple(包括nop)
    都是slf4j门面时间线后面提供的日志实现,所以API完全遵循slf4j进行的设计
    那么我们只需要导入想要使用的日志实现依赖,即可与slf4j无缝衔接
    值得一提的是nop虽然也划分到实现中了,但是他是指不实现日志记录(后续课程)
3.log4j和JUL(这两个需要导入适配器)
    都是slf4j门面时间线前面的日志实现,所以API不遵循slf4j进行设计
    通过适配桥接的技术,完成的与日志门面的衔接

        <!-- 导入log4j适配器依赖 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>

        <!-- 导入jul适配器依赖 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>1.7.25</version>
        </dependency>


在真实生产环境中,slf4j只绑定一个日志实现框架就可以了
绑定多个,默认使用导入依赖的第一个,而且可能会产生没有必要的警告信息

            需求:
                假设我们项目一直以来使用的是log4j日志框架
                但是随着技术和需求的更新换代
                log4j已然不能够满足我们系统的需求
                我们现在就需要将系统中的日志实现重构为 slf4j+logback的组合
                在不触碰java源代码的情况下,将这个问题给解决掉


                此时需要将日志替换为slf4j+logback
                我们既然不用log4j了,就将log4j去除
                将slf4j日志门面和logback的日志实现依赖加入进来
                这样做,没有了log4j环境的支持,编译报错

                这个时候就需要使用桥接器来做这个需求了
                桥接器解决的是项目中日志的重构问题,当前系统中存在之前的日志API,
                可以通过桥接转换到slf4j的实现

                桥接器的使用步骤:
                1.去除之前旧的日志框架依赖
                    <dependency>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                        <version>1.2.17</version>
                    </dependency>
                2.添加slf4j提供的桥接组件
                    log4j相关的桥接器
                    <dependency>
                        <groupId>org.slf4j</groupId>
                        <artifactId>log4j-over-slf4j</artifactId>
                        <version>1.7.25</version>
                    </dependency>
                  桥接器加入后,代码编译就不报错了

 

 

注意:
    在桥接器加入之后,适配器就没有必要加入了
    桥接器和适配器不能同时导入依赖
    桥接器如果配置在适配器的上方,则运行报错,不同同时出现
    桥接器如果配置在适配器的下方,则不会执行桥接器,没有任何的意义

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java 界里有许多实现日志功能的工具,最早得到广泛使用的是 log4j,许多应用程序的日志部分都交给了 log4j,不过作为组件开发者,他们希望自己的组件不要紧紧依赖某一个工具,毕竟在同一个时候还有很多其他很多日志工具,假如一个应用程序用到了两个组件,恰好两个组件使用不同的日志工具,那么应用程序就会有两份日志输出了。 为了解决这个问题,Apache Commons Logging (之前叫 Jakarta Commons Logging,JCL)粉墨登场,JCL 只提供 log 接口,具体的实现则在运行时动态寻找。这样一来组件开发者只需要针对 JCL 接口开发,而调用组件的应用程序则可以在运行时搭配自己喜好的日志实践工具。 所以即使到现在你仍会看到很多程序应用 JCL + log4j 这种搭配,不过当程序规模越来越庞大时,JCL的动态绑定并不是总能成功,具体原因大家可以 Google 一下,这里就不再赘述了。解决方法之一就是在程序部署时静态绑定指定的日志工具,这就是 SLF4J 产生的原因。 跟 JCL 一样,SLF4J 也是只提供 log 接口,具体的实现是在打包应用程序时所放入的绑定器(名字为 slf4j-XXX-version.jar)来决定,XXX 可以是 log4j12, jdk14, jcl, nop 等,他们实现了跟具体日志工具(比如 log4j)的绑定及代理工作。举个例子:如果一个程序希望用 log4j 日志工具,那么程序只需针对 slf4j-api 接口编程,然后在打包时再放入 slf4j-log4j12-version.jar 和 log4j.jar 就可以了。 现在还有一个问题,假如你正在开发应用程序所调用的组件当中已经使用了 JCL 的,还有一些组建可能直接调用了 java.util.logging,这时你需要一个桥接器(名字为 XXX-over-slf4j.jar)把他们的日志输出重定向到 SLF4J,所谓的桥接器就是一个假的日志实现工具,比如当你把 jcl-over-slf4j.jar 放到 CLASS_PATH 时,即使某个组件原本是通过 JCL 输出日志的,现在却会被 jcl-over-slf4j “骗到”SLF4J 里,然后 SLF4J 又会根据绑定器把日志交给具体的日志实现工具。过程如下 Component | | log to Apache Commons Logging V jcl-over-slf4j.jar — (redirect) —> SLF4j —> slf4j-log4j12-version.jar —> log4j.jar —> 输出日志 看到上面的流程图可能会发现一个有趣的问题,假如在 CLASS_PATH 里同时放置 log4j-over-slf4j.jar 和 slf4j-log4j12-version.jar 会发生什么情况呢?没错,日志会被踢来踢去,最终进入死循环。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值