论坛首页 Java企业应用论坛

读commons-logging源码有感

浏览 2887 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-09-15  
转载请注明出处http://chillwarmoon.iteye.com
昨天读了一下commons-logging和log4j的部分源码,收获不少。使用日志时,为什么要两个包全部包含到程序中,这两个包之间的关系如何,是怎么样关联起来的?当我们使用日志时为何只依赖于commons-logging所定义的接口,这些接口与log4j是什么关系?两个日志的配置文件在配置时是否有冲突?在分析完代码之后,这些问题迎刃而解。
一、对commons-logging源码分析
   在程序中使用日志时,经常将两个包放到程序的classpath目录下,在程序中调用LogFactory.getLog("XXX"),返回的是Log对象,无论是LogFactory,还是Log,都与log4j无关,但是在classpath中,我们需要配置log4j.properties,其中规定了一些log4j的使用属性。
   1.首先从LogFactory.getLog("XXX")入手进行分析。在LogFactory第一次使用时调用静态块,初始化属性thisClassLoader为加载LogFactory的classLoader。在方法getLog(String arg)中,调用getFactory().getInstance(name)。
   2.getFactory()
   (1)得到当前线程的contextClassLoader,以contextClassLoader为关键字查找缓存中是否有相应的factory存在,如果有,则返回该factory;
   (2)从contextClassLoader或者systemClassLoader中得到资源commons-logging.properties,若该配置文件中的use_tccl属性为false,则baseContextClassLoader指定为thisClassLoader,否则为contextClassLoader;
   (3)建立factory
      若通过System.setProperty得到以org.apache.commons.logging.LogFactory为key的值,则以该值为类名字来newFactory
      若通过contextClassLoader找到资源META-INF/services/org.apache.commons.logging.LogFactory,则以资源中规定的类名字来newFactory
      若通过commons-logging.properties得到以org.apache.commons.logging.LogFactory为key的值,则以该值为类名字来newFactory
      默认以类LogFactoryImpl来newFactory
   (4)以contextClassLoader来缓存建立的factory
   通过分析容易知道,这里是以默认的方式来建立的factory并缓存起来的。即factory对象是通过实例化LogFactoryImpl来建立的。
   3.getInstance():
   (1)以name为关键字查看缓存是否有Log对象存在,如果有则返回;
   (2)发现Log的实现方式:
      若在commons-logging.properties得到以org.apache.commons.logging.Log为key的值,则以该值为类名字来createLogFromClass
      依次以Log4JLogger、Jdk14Logger、Jdk13LumberjackLogger、SimpleLog为类名字来createLogFromClass,
      如果建立成功则返回该Log实现,注意这里的实现是commons-logging中的实现。
   (3)以name为参数,调用得到的Log实现的构造函数,返回Log对象。
二、关键点
   1.如何createLogFromClass
     (1)首先得到的是baseClassLoader。若useTCCL为false,则为thisClassLoader;若没有指定该值,则选择TCCL和TCL中的一个Lowest作为baseClassLoader,例如:如果TCCL是TCL的父classLoader,则选择TCL。一般而言,Lowest的ClassLoader为TCCL。
     (2)若baseClassLoader不为空,则利用baseClassLoader来找到资源Log4JLogger.class,否则利用systemClassLoader找到资源Log4JLogger.class。并用该classLoader加载该Log类。
   2.与log4j的联系
     由baseClassLoader加载的Log类,是commons-logging中的类,在Log4JLogger中存在有对log4j中的Logger类的引用,因此在Log4JLogger构造函数中对Logger属性进行了初始化,以后的Log.debug,Log.info等方法完全是委派到log4j中的logger属性来执行的。
     因此在程序中,我们只看到commons-logging而并没有见到log4j的API。
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics