Java - 日志体系_Apache Commons Logging(JCL)日志接口库

文章目录

  • 官网
  • 1. 什么是JCL?
  • 2. JCL的主要特点
  • 3. JCL的核心组件
  • 4. JCL的实现机制
  • 5. SimpleLog 简介
  • 6. Code
    • Example 1 : 默认日志实现 (JCL 1.3.2版本)
    • Example 2 : JCL (1.2版本) + Log4J 【安全风险高,请勿使用】
  • 7. 使用场景与优点
  • 8. 常见问题
  • 9. 动态绑定机制源码分析
    • getFactory
    • LogFactoryImpl
  • 10. 总结

在这里插入图片描述


官网

https://commons.apache.org/proper/commons-logging/

在这里插入图片描述


1. 什么是JCL?

Apache Commons Logging(简称 JCL)是一个轻量级的日志接口库,提供了日志记录的抽象层。它允许开发人员编写独立于具体日志实现的代码,而具体的日志实现(如Log4j、SLF4J或java.util.logging)可以在运行时配置。这种设计简化了日志库的集成和切换。


2. JCL的主要特点

  • 灵活性:通过抽象层,可以自由选择日志实现。
  • 自动发现机制:运行时动态发现类路径中的可用日志实现。
  • 兼容性:支持主流日志框架,如Log4j、SLF4J和java.util.logging
  • 简单易用:只需依赖commons-logging.jar,无需复杂配置。

3. JCL的核心组件

  • Log 接口
    提供通用的日志记录方法(如debuginfowarnerrorfatal)。

    Log log = LogFactory.getLog(YourClass.class);
    log.info("信息日志");
    log.error("错误日志");
    
  • LogFactory 类
    用于创建Log接口的实例。LogFactory实现了日志系统的自动发现和绑定。


4. JCL的实现机制

JCL使用自动发现机制选择合适的日志实现:

  1. 首先检查类路径中是否存在Log4j,如果存在则使用Log4j (高版本的JCL已经移除了对log4j的支持)
  2. 如果找不到Log4j,JCL会检查java.util.logging并使用它。
  3. 如果前两个都不可用,则使用内置的SimpleLog作为默认实现。

可以通过配置文件commons-logging.properties显式指定日志实现。例如:

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

5. SimpleLog 简介

JCL内置的SimpleLog是一个轻量级实现,适用于没有复杂日志需求的小型项目。
它通过系统属性进行配置,例如:

  • org.apache.commons.logging.simplelog.defaultlog:设置默认日志级别。
  • org.apache.commons.logging.simplelog.showdatetime:是否显示日期时间。

6. Code

POM

  <dependency>
   	 <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.3.2</version>
  </dependency>

Example 1 : 默认日志实现 (JCL 1.3.2版本)

package com.artisan.jcl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class JavaCommonsLoggingTest {

    private static final Log log = LogFactory.getLog(JavaCommonsLoggingTest.class);

    public static void main(String[] args) {

        log.info("这是信息日志");
        log.warn("这是警告日志");
        log.error("这是错误日志");
    }
}

在这里插入图片描述


Example 2 : JCL (1.2版本) + Log4J 【安全风险高,请勿使用】

log4j1从2005年11月更新到2012年3月, 最新的依赖(May 26, 2012)

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

2015年8月5日,项目管理委员会宣布Log4j 1.x已End Of Life 。建议用户使用Log4j 1升级到Apache Log4j 2

在这里插入图片描述
为了演示这种组合,我们将JCL降级到1.2版本

pom

   <!-- Jakarta Commons Logging -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- Log4j 核心依赖 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

log4j.properties

# 设置根日志记录器的日志级别为 DEBUG,并将其输出到控制台和文件
log4j.rootLogger=DEBUG, console, file

# 配置控制台输出
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

# 可选:配置日志文件滚动
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=application.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

# 可选:配置特定包的日志级别
log4j.logger.com.artisan=DEBUG

Code

package com.artisan.jcl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class JavaCommonsLoggingTest {

    private static final Log logger = LogFactory.getLog(JavaCommonsLoggingTest.class);

    public static void main(String[] args) {
        logger.trace("This is a trace message");
        logger.debug("This is a debug message");
        logger.info("This is an info message");
        logger.warn("This is a warning message");
        logger.error("This is an error message");
        logger.fatal("This is a fatal message");
    }
}

输出

在这里插入图片描述


7. 使用场景与优点

  • 适用于需要在多个日志框架之间切换的场景。
  • 提供了对遗留系统的支持,使其能够与现代日志框架协同工作。
  • 适合中间件开发,避免直接绑定特定的日志框架。

8. 常见问题

  • 为什么不直接使用SLF4J?
    JCL比SLF4J更早出现,仍被许多遗留系统使用。如果是全新项目,建议考虑SLF4J,它解决了JCL的一些局限性。

  • 性能是否有损耗?
    JCL的动态绑定机制在启动时可能略有开销,但运行时性能与直接使用日志实现接近。


9. 动态绑定机制源码分析

让我们以LogFactory.getLog(JavaCommonsLoggingTest.class) 为切入口 ,

  /**
 * 获取指定类的日志记录器实例
 * 
 * @param clazz 要获取日志记录器的类
 * @return 指定类的日志记录器实例
 * @throws LogConfigurationException 如果日志配置存在错误,则抛出此异常
 */
public static Log getLog(final Class<?> clazz) throws LogConfigurationException {
    // 调用日志工厂的实例方法获取日志记录器
    return getFactory().getInstance(clazz);
}

成功
失败
开始
获取 LogFactory 实例
通过 LogFactory 获取日志记录器
返回日志记录器
抛出 LogConfigurationException

getFactory

重点看下: getFactory()

主要功能是根据一系列优先级规则查找并返回一个 LogFactory 实例。

  1. 获取类加载器:首先获取当前线程的上下文类加载器。
  2. 检查缓存:如果该类加载器已经有一个对应的 LogFactory 实例,则直接返回该实例。
  3. 加载配置文件:尝试从 commons-logging.properties 文件中读取配置信息。
  4. 确定是否使用TCCL:根据配置文件中的 use_tccl 属性决定是否使用线程上下文类加载器。
  5. 查找实现类
    • 首先尝试通过系统属性 org.apache.commons.logging.LogFactory 查找。
    • 如果未找到,尝试使用 JDK 1.3 的服务发现机制。
    • 如果仍未找到,尝试从配置文件中查找。
    • 最后,尝试使用默认的实现类 org.apache.commons.logging.impl.LogFactoryImpl
  6. 创建并缓存实例:创建 LogFactory 实例并将其缓存。
成功
命中
未命中
开始
获取类加载器
检查缓存
返回缓存实例
加载配置文件
确定是否使用TCCL
查找实现类
系统属性查找
服务发现机制查找
配置文件查找
默认实现类
创建并缓存实例
返回实例

假设: 没有org.apache.commons.logging.LogFactory 这个系统配置项,classpath下没有包含META-INF/services/org.apache.commons.logging.LogFactory 这个文件的Jar包、没有commons-logging.properties 文件,只有commons-logging这个jar

LogFactoryImpl

我们来看下 LogFactoryImpl

	    /** Log4JLogger class name */
    private static final String LOGGING_IMPL_LOG4J_LOGGER = "org.apache.commons.logging.impl.Log4JLogger";
    /** Jdk14Logger class name */
    private static final String LOGGING_IMPL_JDK14_LOGGER = "org.apache.commons.logging.impl.Jdk14Logger";
    /** Jdk13LumberjackLogger class name */
    private static final String LOGGING_IMPL_LUMBERJACK_LOGGER =
            "org.apache.commons.logging.impl.Jdk13LumberjackLogger";

    /** SimpleLog class name */
    private static final String LOGGING_IMPL_SIMPLE_LOGGER = "org.apache.commons.logging.impl.SimpleLog";


   private static final String[] classesToDiscover = {
            LOGGING_IMPL_JDK14_LOGGER,
            LOGGING_IMPL_SIMPLE_LOGGER
    };

可知: 默认实现为

 LOGGING_IMPL_JDK14_LOGGER org.apache.commons.logging.impl.Jdk14Logger

log4j 不再是默认实现

在这里插入图片描述

commons-logging的动态绑定机制实现如上,但是这种机制的问题在哪儿呢,由于它使用了ClassLoader寻找和载入底层的日志库, 导致了象OSGI这样的框架无法正常工作,因为OSGI的不同的插件使用自己的ClassLoader。 OSGI的这种机制保证了插件互相独立,然而却使Apache Common-Logging无法工作 。 所以就有了Slf4j这种静态绑定的方案。


10. 总结

JCL为日志记录提供了一种统一的接口,虽然不如SLF4J现代化,但在历史遗留系统中仍有广泛的使用价值。如果需要简化日志实现的切换,JCL是一个可靠的选择。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/943276.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mavlink移植到单片机stm32f103c8t6,实现接收和发送数据

前言&#xff1a; 好久没更新博客了&#xff0c;这两个月真的是异常的忙&#xff0c;白天要忙着公司里的事&#xff0c;晚上还要忙着修改小论文&#xff0c;一点自己的时间都没有了&#xff0c;不过确确实实是学到了很多东西&#xff0c;对无人机的技术研究也更深了一些。不过好…

GitLab的安装与卸载

目录 GitLab安装 GitLab使用 使用前可选操作 修改web端口 修改Prometheus端口 使用方法 GitLab的卸载 环境说明 系统版本 CentOS 7.2 x86_64 软件版本 gitlab-ce-10.8.4 GitLab安装 Gitlab的rpm包集成了它需要的软件&#xff0c;简化了安装步骤&#xff0c;所以直接…

子网掩码计算route命令

子网掩码 - 站长工具 1.子网掩码 子网掩码就是用来遮掩IP地址并划分网段的工具&#xff0c;根据遮掩的位数不同来划分不同的网段。 2.网关 网关(Gateway)又称网间连接器、协议转换器。默认网关在网络层上以实现网络互连&#xff0c;是最复杂的网络互连设备&#xff0c;仅用…

基本操作:iframe、alert

背景 如果你的目标元素出现在一个iframe标签下&#xff0c;则不能直接定位&#xff0c;必须先完成切换才能进行定位操作&#xff0c;如下图 整个理解为一个大的房间&#xff0c;里面是客厅&#xff0c;driver进到客厅后&#xff0c;如果想操作iframe A里的数据&#xff0c;需…

【再学javascript算法之美】前端面试频率比较高的基础算法题

基础算法题练习代码&#xff0c;看看能做出几道题 代码实现 找出字符串中出现次数最多的字符 const array "cncnansdnajsadnjasndjnasjdnjj";// 找出出现次数最多的字符 let obj {}; for (let index 0; index < array.length; index) {const element array[…

flask后端开发(8):Flask连接MySQL数据库+ORM增删改查

目录 数据库初始化数据库连接创建数据库表添加用户查询用户更新用户删除 在Flask中&#xff0c;很少会使用pymysql直接写原生SQL语句去操作数据库&#xff0c;更多的是通过SQLAichemy提供的ORM技术&#xff0c;类似于操作普通Python对象一样实现数据库的增删改查操作&#xff0…

视频会议是如何实现屏幕标注功能的?

现在主流的视频会议软件都有屏幕标注功能&#xff0c;屏幕标注功能给屏幕分享者讲解分享内容时提供了极大的方便。那我们以傲瑞视频会议&#xff08;OrayMeeting&#xff09;为例&#xff0c;来讲解屏幕标注是如何实现的。 傲瑞会议的PC端&#xff08;Windows、信创Linux、银河…

使用Streamlit部署机器学习模型

机器学习&#xff1a; 计算机能够从经验中学习&#xff0c;而无需明确编程。机器学习是目前最热门的领域之一&#xff0c;世界各地的顶级公司都在使用它来改善他们的服务和产品。但是没有使用在Jupyter Notebook中训练的机器学习模型。因此&#xff0c;我们需要部署这些模型&am…

解线性方程组

直接三角分解&#xff08;LU分解&#xff0c;Doolittle分解&#xff09; ATM分解&#xff08;追赶法&#xff0c;Crout分解&#xff0c;克劳特分解&#xff09; 平方根法&#xff08;Cholesky分解&#xff0c;乔列斯基分解&#xff09; 矩阵的范数

聊一聊 C#前台线程 如何阻塞程序退出

一&#xff1a;背景 1. 讲故事 这篇文章起源于我的 C#内功修炼训练营里的一位朋友提的问题&#xff1a;后台线程的内部是如何运转的 ? &#xff0c;犹记得C# Via CLR这本书中 Jeffery 就聊到了他曾经给别人解决一个程序无法退出的bug&#xff0c;最后发现是有一个 Backgrond…

带着国标充电器出国怎么办? 适配器模式(Adapter Pattern)

适配器模式&#xff08;Adapter Pattern&#xff09; 适配器模式适配器模式&#xff08;Adapter Pattern&#xff09;概述talk is cheap&#xff0c; show you my code总结 适配器模式 适配器模式&#xff08;Adapter Pattern&#xff09;是面向对象软件设计中的一种结构型设计…

【技术实战】R语言统计分析与可视化从入门到精通

前言 随着大数据时代的到来&#xff0c;数据分析已经成为各行各业的重要技能。R语言作为一种强大的统计分析和数据可视化工具&#xff0c;广泛应用于科学研究、数据分析和商业决策支持。 本文将带领读者从入门到精通&#xff0c;掌握R语言在统计分析和数据可视化方面的核心技…

Milvus×EasyAi:如何用java从零搭建人脸识别应用

如何从零搭建一个人脸识别应用&#xff1f;不妨试试原生Java人工智能算法&#xff1a;EasyAi Milvus 的组合拳。 本文将使用到的软件和工具包括&#xff1a; EasyAi&#xff1a;人脸特征向量提取Milvus&#xff1a;向量数据库用于高效存储和检索数据。 01. EasyAi&#xff1a;…

【运维】文件存储公共盘升级及数据迁移

记录一下升级公共盘及数据迁移的经历 一、背景&#xff1a; 因旧公共盘性能较差&#xff0c;故公司打算采购一批主机&#xff0c;用于替换旧的公共盘。 二、迁移计划&#xff1a; 选择了用户使用较少的星期五晚上到星期日晚上作为迁移时间窗口&#xff0c;同时选择了fastco…

消息队列(一)消息队列的工作流程

什么是消息队列 首先&#xff0c;代入一个场景&#xff0c;我现在做一个多系统的集成&#xff0c;分别有系统A、B、C、D四个系统&#xff0c;A系统因为使用产生了业务数据&#xff0c;B、C、D需要使用这些数据做相关的业务处理和运算&#xff0c;最基本的做法就是通过接口通信…

SAP配置网络打印机

1、网络打印机 在项目中需要用打印机打印表单&#xff0c;如果不配置网络打印机&#xff0c;通常需要通过连接特定的计算机&#xff08;如打印服务器&#xff09;来进行打印&#xff0c;或者使用本地连接的打印机&#xff0c;这样每台计算机可能需要单独配置打印机或安装驱动&…

GB/T34944-2017 《Java语言源代码漏洞测试规范》解读——安全功能

GB/T34944-2017 《Java语言源代码漏洞测试规范》标准是软件测试实验室开展代码测试活动的重要依据&#xff0c;也是软件测试实验室申请代码测试CNAS/CMA实验室认证时所依据的标准方法。本系列文章一起解读GB/T34944-2017 《Java语言源代码漏洞测试规范》&#xff0c;前面的文章…

NLP 中文拼写检测纠正论文 C-LLM Learn to CSC Errors Character by Character

拼写纠正系列 NLP 中文拼写检测实现思路 NLP 中文拼写检测纠正算法整理 NLP 英文拼写算法&#xff0c;如果提升 100W 倍的性能&#xff1f; NLP 中文拼写检测纠正 Paper java 实现中英文拼写检查和错误纠正&#xff1f;可我只会写 CRUD 啊&#xff01; 一个提升英文单词拼…

监听器listener

文章目录 监听器( listener)对Application内置对象监听的语法和配置对session内置对象监听的语法和配置 监听器( listener) 对象与对象的关系&#xff1a; 继承关联 tomcat一启动创建的顺序&#xff1a;监听器&#xff0c;config&#xff0c;application(全局初始化参数)&am…

LabVIEW数字式气压计自动检定系统

开发了一个基于LabVIEW开发的数字式气压计自动检定系统。在自动化检定PTB220和PTB210系列数字气压计&#xff0c;通过优化硬件组成和软件设计&#xff0c;实现高效率和高准确度的检定工作&#xff0c;有效降低人力成本并提升操作准确性。 项目背景 随着自动气象站的广泛部署&a…