ToB企服应用市场:ToB评测及商务社交产业平台
标题:
Java - 日志体系_Apache Commons Logging(JCL)日志接口库
[打印本页]
作者:
灌篮少年
时间:
前天 15:14
标题:
Java - 日志体系_Apache Commons Logging(JCL)日志接口库
官网
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 接口
提供通用的日志记录方法(如debug、info、warn、error、fatal)。
Log log = LogFactory.getLog(YourClass.class);
log.info("信息日志");
log.error("错误日志");
复制代码
LogFactory 类
用于创建Log接口的实例。LogFactory实现了日志系统的自动发现和绑定。
4. JCL的实现机制
JCL利用
自动发现机制
选择合适的日志实现:
首先查抄类路径中是否存在Log4j,假如存在则利用Log4j (
高版本的JCL已经移除了对log4j的支持
)
假如找不到Log4j,JCL会查抄java.util.logging并利用它。
假如前两个都不可用,则利用内置的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);
}
复制代码
getFactory
重点看下: getFactory()
主要功能是根据一系列优先级规则查找并返回一个 LogFactory 实例。
获取类加载器
:首先获取当火线程的上下文类加载器。
查抄缓存
:假如该类加载器已经有一个对应的 LogFactory 实例,则直接返回该实例。
加载设置文件
:实验从 commons-logging.properties 文件中读取设置信息。
确定是否利用TCCL
:根据设置文件中的 use_tccl 属性决定是否利用线程上下文类加载器。
查找实现类
:
首先实验通过系统属性 org.apache.commons.logging.LogFactory 查找。
假如未找到,实验利用 JDK 1.3 的服务发现机制。
假如仍未找到,实验从设置文件中查找。
最后,实验利用默认的实现类 org.apache.commons.logging.impl.LogFactoryImpl。
创建并缓存实例
:创建 LogFactory 实例并将其缓存。
假设: 没有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是一个可靠的选择。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4