• log4j源码解析


    前言:本文将在slf4j的基础上解释log4j的应用,阅读本文前可先行阅读SLF4J源码解析-LoggerFactory(二)

    前言概要

    在前言中提到的slf4j的基础,其主要是通过logback的api来解释slf4j的工作原理,而本文的log4j与logback不同,其可以和slf4j结合使用,也可以脱离slf4j单独使用。

    Maven依赖

    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-api</artifactId>
    			<version>1.6.6</version>
    		</dependency>
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-log4j12</artifactId>
    			<version>1.6.6</version>
    		</dependency>
    		<dependency>
    			<groupId>log4j</groupId>
    			<artifactId>log4j</artifactId>
    			<version>1.2.16</version>
    		</dependency>
    

    此依赖包含了可以使用slf4j对应的扩展方法获取日志对象,也可以独立使用log4j本身的日志对象

    第一种方式-结合slf4j使用

    调用方式如下

    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("test") ;
    

    由上可知是通过LoggerFactory#getLogger()方法来获取日志对象,我们分析过其是通过StaticLoggerBinder.getSingleton().getLoggerFactory()工厂类来获取日志对象的,其中StaticLoggerBinder一般都是供其他整合jar来实现的,本文特指slf4j-log4j12-1.6.6.jar。我们看下log4j是如何处理的

    log4j获取LoggerFactory对象

    直接看log4j对StaticLoggerBinder的复写

      private StaticLoggerBinder() {
        //直接使用的是Log4jLoggerFactory工厂类来获取日志对象
        loggerFactory = new Log4jLoggerFactory();
        try {
          Level level = Level.TRACE;
        } catch (NoSuchFieldError nsfe) {
          Util
              .report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
        }
      }
    

    可以看出其是通过Log4jLoggerFactory来获取日志对象的。

    Log4jLoggerFactory获取日志对象

    先看下其构造函数

      public Log4jLoggerFactory() {
        //缓存对象
        loggerMap = new HashMap();
      }
    

    再看确切方法源码

      public Logger getLogger(String name) {
        Logger slf4jLogger = null;
        // protect against concurrent access of loggerMap
        synchronized (this) {
            slf4jLogger = (Logger) loggerMap.get(name);
          if (slf4jLogger == null) {
            org.apache.log4j.Logger log4jLogger;
            if(name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME)) {
               log4jLogger = LogManager.getRootLogger();
            } else {
              log4jLogger = LogManager.getLogger(name);
            }
            slf4jLogger = new Log4jLoggerAdapter(log4jLogger);
            loggerMap.put(name, slf4jLogger);
          }
        }
        return slf4jLogger;
      }
    

    最终日志对象都是通过LogManager.getLogger()方法来获取到的,上述的Log4jLoggerAdapter只是slf4j-api下Logger的接口实现类,此处类似于针对于log4j的适配器。

    第二种方式-独立使用

    直接采用log4j本身自带的日志工厂类来获取,使用方式如下

    private static final org.apache.log4j.Logger log = org.apache.log4j.LogManager("test");
    

    log4j的加载逻辑的实现均可以通过LogManager类来查看,本文则不进行简析了,此处只作总结

    1. 读取系统变量log4j.defaultInitOverride,如果没指定或者指定的值为false则继续读取。默认为false

    2. 读取系统变量log4j.configuration,如果指定了配置文件路径则读取,反之则往下

    3. 读取classpath路径下的log4j.xml,如果不存在则继续往下

    4. 读取classpath路径下的log4j.properties,找不到则打印警告信息

    5. 其中关于配置文件的加载类也可以自行指定,由系统变量log4j.configurationClass指定

    小结

    1. log4j是我们常用的日志打印工具,本文在slf4j的基础上简单的分析了log4j日志工具的使用,不管是结合slf4j还是独立使用自身的api,均是通过log4j-api中的LogManager#getLogger()来获取日志对象

    2. 其中对于log4j的配置文件读取可见本文的详细内容

  • 相关阅读:
    MS CRM 2011的自定义和开发(10)——CRM web服务介绍(第一部分)——IDiscoveryService
    MS CRM 2011的自定义和开发(7)——视图编辑器(第二部分)
    MS CRM 2011 SDK 5.06版本已经发布
    MS CRM 2011的自定义和开发(11)——插件(plugin)开发(一)
    近来遇到的MS CRM 2011方面的几个问题
    MS CRM 2011的自定义与开发(6)——表单编辑器(第二部分)
    Microsoft Dynamics CRM 2011中,Lookup字段的赋值
    MS CRM 2011的自定义和开发(6)——表单编辑器(第三部分)
    Visual Studio 目标框架造成 命名空间“Microsoft”中不存在类型或命名空间名称“Crm”。是否缺少程序集引用中错误的处理
    一步步学习Reporting Services(二) 在报表中使用简单的参数作为查询条件
  • 原文地址:https://www.cnblogs.com/question-sky/p/7469596.html
Copyright © 2020-2023  润新知