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的主要特点



3. JCL的核心组件



4. JCL的实现机制

JCL利用自动发现机制选择合适的日志实现:
可以通过设置文件commons-logging.properties显式指定日志实现。例如:
  1. org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
复制代码

5. SimpleLog 简介

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


6. Code

   POM
  1.   <dependency>
  2.             <groupId>commons-logging</groupId>
  3.       <artifactId>commons-logging</artifactId>
  4.       <version>1.3.2</version>
  5.   </dependency>
复制代码
Example 1 : 默认日志实现 (JCL 1.3.2版本)

  1. package com.artisan.jcl;
  2. import org.apache.commons.logging.Log;
  3. import org.apache.commons.logging.LogFactory;
  4. public class JavaCommonsLoggingTest {
  5.     private static final Log log = LogFactory.getLog(JavaCommonsLoggingTest.class);
  6.     public static void main(String[] args) {
  7.         log.info("这是信息日志");
  8.         log.warn("这是警告日志");
  9.         log.error("这是错误日志");
  10.     }
  11. }
复制代码


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

log4j1从2005年11月更新到2012年3月, 最新的依赖(May 26, 2012)
  1. <dependency>
  2.     <groupId>log4j</groupId>
  3.     <artifactId>log4j</artifactId>
  4.     <version>1.2.17</version>
  5. </dependency>
复制代码
2015年8月5日,项目管理委员会公布Log4j 1.x已End Of Life 。发起用户利用Log4j 1升级到Apache Log4j 2

为了演示这种组合,我们将JCL降级到1.2版本
   pom
  1.    <!-- Jakarta Commons Logging -->
  2.         <dependency>
  3.             <groupId>commons-logging</groupId>
  4.             <artifactId>commons-logging</artifactId>
  5.             <version>1.2</version>
  6.         </dependency>
  7.         <!-- Log4j 核心依赖 -->
  8.         <dependency>
  9.             <groupId>log4j</groupId>
  10.             <artifactId>log4j</artifactId>
  11.             <version>1.2.17</version>
  12.         </dependency>
复制代码
  log4j.properties
  1. # 设置根日志记录器的日志级别为 DEBUG,并将其输出到控制台和文件
  2. log4j.rootLogger=DEBUG, console, file
  3. # 配置控制台输出
  4. log4j.appender.console=org.apache.log4j.ConsoleAppender
  5. log4j.appender.console.layout=org.apache.log4j.PatternLayout
  6. log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
  7. # 可选:配置日志文件滚动
  8. log4j.appender.file=org.apache.log4j.RollingFileAppender
  9. log4j.appender.file.File=application.log
  10. log4j.appender.file.MaxFileSize=10MB
  11. log4j.appender.file.MaxBackupIndex=10
  12. log4j.appender.file.layout=org.apache.log4j.PatternLayout
  13. log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
  14. # 可选:配置特定包的日志级别
  15. log4j.logger.com.artisan=DEBUG
复制代码
  Code
  1. package com.artisan.jcl;
  2. import org.apache.commons.logging.Log;
  3. import org.apache.commons.logging.LogFactory;
  4. public class JavaCommonsLoggingTest {
  5.     private static final Log logger = LogFactory.getLog(JavaCommonsLoggingTest.class);
  6.     public static void main(String[] args) {
  7.         logger.trace("This is a trace message");
  8.         logger.debug("This is a debug message");
  9.         logger.info("This is an info message");
  10.         logger.warn("This is a warning message");
  11.         logger.error("This is an error message");
  12.         logger.fatal("This is a fatal message");
  13.     }
  14. }
复制代码
  输出
  


7. 利用场景与长处



8. 常见问题



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

让我们以LogFactory.getLog(JavaCommonsLoggingTest.class) 为切入口 ,
  1.   /**
  2. * 获取指定类的日志记录器实例
  3. *
  4. * @param clazz 要获取日志记录器的类
  5. * @return 指定类的日志记录器实例
  6. * @throws LogConfigurationException 如果日志配置存在错误,则抛出此异常
  7. */
  8. public static Log getLog(final Class<?> clazz) throws LogConfigurationException {
  9.     // 调用日志工厂的实例方法获取日志记录器
  10.     return getFactory().getInstance(clazz);
  11. }
复制代码
   
getFactory

重点看下: getFactory()
主要功能是根据一系列优先级规则查找并返回一个 LogFactory 实例。
     假设: 没有org.apache.commons.logging.LogFactory 这个系统设置项,classpath下没有包罗META-INF/services/org.apache.commons.logging.LogFactory 这个文件的Jar包、没有commons-logging.properties 文件,只有commons-logging这个jar
LogFactoryImpl

我们来看下 LogFactoryImpl ,
  1.             /** Log4JLogger class name */
  2.     private static final String LOGGING_IMPL_LOG4J_LOGGER = "org.apache.commons.logging.impl.Log4JLogger";
  3.     /** Jdk14Logger class name */
  4.     private static final String LOGGING_IMPL_JDK14_LOGGER = "org.apache.commons.logging.impl.Jdk14Logger";
  5.     /** Jdk13LumberjackLogger class name */
  6.     private static final String LOGGING_IMPL_LUMBERJACK_LOGGER =
  7.             "org.apache.commons.logging.impl.Jdk13LumberjackLogger";
  8.     /** SimpleLog class name */
  9.     private static final String LOGGING_IMPL_SIMPLE_LOGGER = "org.apache.commons.logging.impl.SimpleLog";
  10.    private static final String[] classesToDiscover = {
  11.             LOGGING_IMPL_JDK14_LOGGER,
  12.             LOGGING_IMPL_SIMPLE_LOGGER
  13.     };
复制代码
可知: 默认实现为
  1. 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