004-log-common-logging,Apache整合日志框架JCL门面框架、JCL+log4j

1、概述

  Jakarta Commons Logging (JCL)提供的是一个日志(Log)接口(interface),同时兼顾轻量级和不依赖于具体的日志实现工具。它提供给中间件/日志工具开发者一个简单的日志操做抽象,容许程序开发人员使用不一样的具体日志实现工具。用户被假定已熟悉某种日志实现工具的更高级别的细节。JCL提供的接口,对其它一些日志工具,包括Log4J, Avalon LogKit, and JDK 1.4等,进行了简单的包装,此接口更接近于Log4J和LogKit的实现。html

  在Logging系统中,目前框架都是基于相同的设计,即从一个LogFactory中取得一个命名的Log(Logger)实例,而后使用这个Log(Logger)实例打印debug、info、warn、error等不一样级别的日志。做为两个门面日志系统,Commons Logging和SLF4J也一样采用这样的设计。 
所谓门面日志系统,是指它们自己并不实现具体的日志打印逻辑,它们只是做为一个代理系统,接收应用程序的日志打印请求,而后根据当前环境和配置,选取一个具体的日志实现系统,将真正的打印逻辑交给具体的日志实现系统,从而实现应用程序日志系统的“可插拔”,便可以经过配置或更换jar包来方便的更换底层日志实现系统,而不须要改变任何代码。我的感受SLF4J的实现更加灵活,而且它还提供了Maker和MDC的接口。java

1.一、pom依赖

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

1.二、配置

  建立commons-logging.properties文件,将其放在classpath下,若是是maven项目则将其放在src/main/resource目录下,配置内容以下git

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

1.三、使用

import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ApplicationMain { private static Log logger = LogFactory.getLog(ApplicationMain.class); public static void main(String[] args) { System.out.println(logger.getClass().getName()); // 记录debug级别的信息
        logger.debug("This is debug message."); // 记录info级别的信息
        logger.info("This is info message."); // 记录error级别的信息
        logger.error("This is error message."); } }

2、详细说明

    

2.一、LogFactory获取相对应的Log实现类逻辑

JCL有两个基本的抽象类:Log(基本记录器)和LogFactory(负责建立Log实例)。当commons-logging.jar被加入到 CLASSPATH以后,它会合理地猜想你想用的日志工具,而后进行自我设置,用户根本不须要作任何设置。默认的LogFactory是按照下列的步骤去发现并决定那个日志工具将被使用的(按照顺序,寻找过程会在找到第一个工具时停止): 
  1. 寻找当前factory中名叫org.apache.commons.logging.Log配置属性的值 
  2. 寻找系统中属性中名叫org.apache.commons.logging.Log的值 
  3. 若是应用程序的classpath中有log4j,则使用相关的包装(wrapper)类(Log4JLogger) 
  4. 若是存在Lumberjack版本的Logging系统,则使用Jdk13LumberjackLogger类。 
  5. 若是应用程序运行在jdk1.4的系统中,使用相关的包装类(Jdk14Logger) 
  6. 使用简易日志包装类(SimpleLog) 
  7. 以上步骤都失败,则抛出LogConfigurationException。github

LogFactory使用动态查找机制进行日志实例化,执行顺序为:common-logging.properties---->系统环境变量------->log4j--->jul--->simplelog---->nooplogapache

org.apache.commons.logging.Log的具体实现:数组

  org.apache.commons.logging.Log的具体实现有以下: 
  - org.apache.commons.logging.impl.Jdk14Logger 使用JDK1.4。 
  - org.apache.commons.logging.impl.Log4JLogger 使用Log4J。 
  - org.apache.commons.logging.impl.LogKitLogger 使用 avalon-Logkit。 
  - org.apache.commons.logging.impl.SimpleLog common-logging自带日志实现类。它实现了Log接口,把日志消息都输出到系统错误流System.err 中。 
  - org.apache.commons.logging.impl.NoOpLog common-logging自带日志实现类。它实现了Log接口。 其输出日志的方法中不进行任何操做。app

2.二、日志级别

1)fatal 很是严重的错误,致使系统停止。指望这类信息能当即显示在状态控制台上。框架

2)error 其它运行期错误或不是预期的条件。指望这类信息能当即显示在状态控制台上。maven

3)warn 使用了不同意使用的API、很是拙劣使用API, '几乎就是'错误, 其它运行时不合须要和不合预期的状态但还不必称为 "错误"。指望这类信息能当即显示在状态控制台上。ide

4)info 运行时产生的有意义的事件。指望这类信息能当即显示在状态控制台上。

5)debug 系统流程中的细节信息。指望这类信息仅被写入log文件中。

6)trace 更加细节的信息。指望这类信息仅被写入log文件中。

如上述配置了SimpleLog,增长simplelog.properties配置文件,放到classpath下,若是是maven则放到src/main/resource目录下,配置内容参考:
org.apache.commons.logging.simplelog.defaultlog=TRACE

2.三、LogFactory实现原理

  LogFactory做为log的工厂存在,使用动态查找机制进行log实例的获取,具体执行步骤以下:

  ①首先在classpath下寻找commons-logging.properties文件。若是找到,则使用其中定义的Log实现类;若是找不到,则在查找是否已定义系统环境变量org.apache.commons.logging.Log,找到则使用其定义的Log实现类;

  ②查看classpath中是否有Log4j的包,若是发现,则自动使用Log4j做为日志实现类;

  ③使用JDK自身的日志实现类(JDK1.4之后才有日志实现类);

  ④使用commons-logging本身提供的一个简单的日志实现类SimpleLog;

  上述步骤当LogFactory成功找到一个日志实现以后就会中止

  LogFactory的核心步骤在于discoverLogImplementation方法,源码分析以下:

if (isDiagnosticsEnabled()) { this.logDiagnostic("Discovering a Log implementation..."); } this.initConfiguration(); Log result = null; //从common-logging.properties文件中提取org.apache.commons.logging.Log这个变量的value
        String specifiedLogClassName = this.findUserSpecifiedLogClassName(); //配置文件中存在该变量则实例化
        if (specifiedLogClassName != null) { if (isDiagnosticsEnabled()) { this.logDiagnostic("Attempting to load user-specified log class '" + specifiedLogClassName + "'..."); } //核验相应日志对象是否存在
            result = this.createLogFromClass(specifiedLogClassName, logCategory, true); //若是日志对象不存在,则报错
            if (result == null) { StringBuffer messageBuffer = new StringBuffer("User-specified log class '"); messageBuffer.append(specifiedLogClassName); messageBuffer.append("' cannot be found or is not useable."); this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.Log4JLogger"); this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.Jdk14Logger"); this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.Jdk13LumberjackLogger"); this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.SimpleLog"); throw new LogConfigurationException(messageBuffer.toString()); } else { return result; } } else { //当日志文件中不存在该变量时,按照机制遍历classesToDiscover字符串数组

            if (isDiagnosticsEnabled()) { this.logDiagnostic("No user-specified Log implementation; performing discovery using the standard supported logging implementations..."); } //遍历classesToDiscover字符串数组获取日志实例(动态查找机制)
            for(int i = 0; i < classesToDiscover.length && result == null; ++i) { result = this.createLogFromClass(classesToDiscover[i], logCategory, true); } //到最后仍旧找不到匹配的日志实例,则抛错
            if (result == null) { throw new LogConfigurationException("No suitable Log implementation"); } else { return result; } }

3、common-logging+log4j应用

3.一、POM依赖

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

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

3.二、配置文件

  在commons-logging.properties文件,将log指向log4j,能够不加由于默认的,没有的话会先加载log4j

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

  配置log4j.properties配置【能够参看002-log-log4j

### 设置### log4j.rootLogger = debug,stdout,D,E ### 输出信息到控制抬 ### log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n ### 输出DEBUG 级别以上的日志到 ### log4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = log.log log4j.appender.D.Append = true log4j.appender.D.Threshold = DEBUG log4j.appender.D.layout = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n ### 输出ERROR 级别以上的日志到error.log ### log4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File =error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
View Code

3.二、java代码依旧使用logging代码便可

import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ApplicationMain { private static Log logger = LogFactory.getLog(ApplicationMain.class); public static void main(String[] args) { System.out.println(logger.getClass().getName()); // 记录debug级别的信息
        logger.debug("This is debug message."); // 记录info级别的信息
        logger.info("This is info message."); // 记录error级别的信息
        logger.error("This is error message."); } }

输出

org.apache.commons.logging.impl.Log4JLogger [DEBUG] 2019-06-21 14:07:37,823 method:com.github.bjlhx15.common.study.log.ApplicationMain.main(ApplicationMain.java:13) This is debug message. [INFO ] 2019-06-21 14:07:37,826 method:com.github.bjlhx15.common.study.log.ApplicationMain.main(ApplicationMain.java:15) This is info message. [ERROR] 2019-06-21 14:07:37,826 method:com.github.bjlhx15.common.study.log.ApplicationMain.main(ApplicationMain.java:17) This is error message.
相关文章
相关标签/搜索