`
pangwu86
  • 浏览: 117515 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Apache Commons-Logging 源码分析

 
阅读更多

Commons-Logging

 

包结构:

 

 

 

org.apache.commons.logging.Log

 

一个接口,定义了五个输出级别(从低到高依次严重)

 

trace (the least serious)

debug

info

warn

error

fatal (the most serious)

 

PS:以下XXX代表某一个日志级别

 

每个级别都有一个isXXXEnabled 方法 可以判断是否启用了这个级别的输出

同时还有两个输出方法:

XXX(Object message)

XXX(Object message, Throwable t)

 

org.apache.commons.logging.LogSource

 

已经被弃用的类,提供了获得log实例对象的方法,LogFactory替代了这个类的作用。

 

不过从这个类中还是可以看到是如何获得log实现类的。

 

首先判断 org.apache.log4j.Logger 是否在classpath中,也就是说默认采用log4j作为实现。

 

其次判断

java.util.logging.Logger org.apache.commons.logging.impl.Jdk14Logger是否存在,将使用jdk1.4提供的log作为底层实现。

 

否则将使用org.apache.commons.logging.impl.NoOpLog作为实现,将不提供log输出。

 

org.apache.commons.logging.LogFactory

 

抽象类,log工厂类,产生log的实例对象。


最常用的方法是getLogClass clazz

 

可以看到方法内代码只有一行: return (getFactory().getInstance(clazz));

 

getInstance是个抽象方法,后面讲解。

 

这里解析下getFactory方法

 

  1. 获得当前线程的classloader,命名为contextClassLoader
  2. 根据contextClassLoader在缓存中获得logFactory,这里的缓存使用的是org.apache.commons.logging.impl.WeakHashTablekeyclassloadervaluelogFactory,如果在缓存中有logFactory则直接返回,没有进入下面的流程
  3. 读取配置文件commons-logging.properties
  4. 如果读到了配置文件,判断其中use_tccl属性,然后设定baseClassLoader是使用contextClassLoader还是使用加载本Class文件的那个classloader(名字为thisClassLoader
  5. 下面生成logFactory,这里会有使用四种方式,依次来尝试生成。
  6. 将生成的logFactory缓存起来
  7. 返回logFactory

第5条种四种方式是:

  • 通过系统属性中寻找org.apache.commons.logging.LogFactoryvalue值,根据值为类名生成logFactory
  • 通过资源META-INF/services/org.apache.commons.logging.LogFactory,获得的值为类名生成logFactor
  • 通过刚才读取的配置文件commons-logging.properties,从中获取以org.apache.commons.logging.LogFactorykeyvalue值,根据值为类名生成logFactory
  • 如果上面都不成功的话,会使用默认的实现类org.apache.commons.logging.impl.LogFactoryImpl来生成logFactory

 

下面来看下默认实现类有什么内容,其中的getInstance是如果运作的。

 

org.apache.commons.logging.impl.LogFactoryImpl

 

主要查看getInstance方法

 

源码如下:

 

        Log instance = (Log) instances.get(name);
        if (instance == null) {
            instance = newInstance(name);
            instances.put(name, instance);
        }
        return (instance);

 

可以看到逻辑很简单,在一个缓存中查找是否有这个log,没有就生成一个,并放到缓存中,这里的name就是传入的className

 

下面主要解析下newInstance方法:

 

首先会判断logConstructor是否为空,第一次必然为空,然后就调用discoverLogImplementation

 

在其方法中,会先查看是否有用户指定的实现类。如果没有则按照下面的顺序,在classpath中去寻找,找到就后进行实例化并返回该实例。

 

顺序如下:

org.apache.commons.logging.impl.Log4JLogger

org.apache.commons.logging.impl.Jdk14Logger

org.apache.commons.logging.impl.Jdk13LumberjackLogger

org.apache.commons.logging.impl.SimpleLog

 

生成log实例会调用方法:createLogFromClass

 

这里会先找到这个实现类的class文件

 

 

URL url;
String resourceName = logAdapterClassName.replace('.', '/') + ".class";
if (currentCL != null) {
    url = currentCL.getResource(resourceName );
} else {
    url = ClassLoader.getSystemResource(resourceName + ".class");
}
 

其实这里的1069行代码,ME觉得应该是个bug,明明resourceName已经加上了.class后缀,这里竟然要再加一遍,估计这个分支很少会跑进去,所以这个错误没有发现吧

 

然后找个加载这个class文件,然后获取构造函数(带有一个String参数),接着实例化。

 

如果这里affectStatecreateLogFromClass最后一个参数)为true的话,会将刚才找到的构造函数,log类名等信息记录下来,方面后面使用。

 

最后返回log实例。

 

下面是关于log接口的几个实现类:

org.apache.commons.logging.impl.Log4JLogger

org.apache.commons.logging.impl.Jdk14Logger

org.apache.commons.logging.impl.Jdk13LumberjackLogger

org.apache.commons.logging.impl.SimpleLog

 

可以看到,前三个都是相当于适配器的功能,也就是说里面实际实现,是委托给其他log框架去完成的,例如log4j,jdk1.4自带的logging等等,最后一个才是该项目提供的log接口的一个实现类。

 

举个例子:

public void debug(Object message, Throwable t) 这个方法

 

Log4JLogger中实现:

 

    public void debug(Object message, Throwable t) {
        getLogger().log(FQCN, Priority.DEBUG, message, t );
    }
 

SimpleLog中实现:

 

    public final void debug(Object message, Throwable t) {
        if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) {
            log(SimpleLog.LOG_LEVEL_DEBUG, message, t);
        }
    }

 

这里的log方法中,可以看到使用了java.io.StringWriter进行输出的。

 


 

总结下就是,commons-logging项目采用了一种动态搜索的机制,在实际运行时,动态的选择log 的实现方式。如果没有log4j,就使用jdk1.4logging,如果再没有,就使用Lumberjack,它是为jdk1.21.3实现了Java日志 API,再没有,那就使用自身提供的一个logSimpleLog)。

 

可以说commons-logging提供了一套简单的日志API给用户,但对于输出格式设定等问题,没有提供必要的API给用户,这点只能靠使用Log4j等更加强大的日志框架来完成,这也可能是为什么采用log4j作为最优先实现的原因吧。

 

项目中使用commons-logging的原因,可能是为了不与log4j死死的绑定在一起,使用commons-logging作为一个中间层,达到解耦的目的。

 

所以说commons-logging 的最大贡献就是为日志输出提供一个统一的接口,并且会在运行时,很方便的自动选择好日志实现系统。

 

 

顺便摘抄一段关于日志级别的信息:

 

确保日志信息在内容上和反应问题的严重程度上的恰当,是非常重要的。

  1. fatal非常严重的错误,导致系统中止。期望这类信息能立即显示在状态控制台上。
  2. error其它运行期错误或不是预期的条件。期望这类信息能立即显示在状态控制台上。
  3.  warn使用了不赞成使用的API、非常拙劣使用API, '几乎就是'错误其它运行时不合需要和不合预期的状态但还没必要称为 "错误"。期望这类信息能立即显示在状态控制台上。
  4. info运行时产生的有意义的事件。期望这类信息能立即显示在状态控制台上。
  5. debug系统流程中的细节信息。期望这类信息仅被写入log文件中。
  6. trace更加细节的信息。期望这类信息仅被写入log文件中。

通常情况下,记录器的级别不应低于info。

也就是说,通常情况下debug的信息不应被写入log文件中。

 

1
4
分享到:
评论
1 楼 cl1154781231 2011-10-31  
有帮助。谢谢!

相关推荐

    commons-logging-1.2源码(commons-logging-1.2-src.zip)

    通过分析`commons-logging-1.2-src`的源码,我们可以发现Commons Logging的设计目标是提供一个轻量级、灵活的日志解决方案,使得开发者可以在不修改代码的情况下切换日志框架。它的接口设计简洁,适配性强大,是Java...

    commons-logging-1.2源码(commons-logging-1.2-src.tar.gz)

    通过分析源码,开发者可以更好地理解Apache Commons Logging的工作原理,这对于自定义日志行为、调试日志问题或构建自己的日志适配器非常有帮助。同时,这也是一种学习通用设计模式和最佳实践的机会,比如工厂模式、...

    commons-logging-1.0.4源码

    在源码分析中,`LogFactory`的实现是关键。它使用`ServiceLoader`机制(自Java 6起)或通过检查系统属性、环境变量、类路径中的配置文件等方式,来找到并加载最适合的日志实现。这种灵活性使得开发者可以在部署时...

    struts2 的类库 commons-logging-1.1 源码

    源码分析可以从以下几个方面进行: 1. **接口设计**:研究 `Log` 接口,了解不同日志级别的用法和语义。 2. **工厂模式**:探索 `LogFactory` 类,理解如何根据环境自动选择日志实现。 3. **适配器模式**:查看具体...

    commons-logging-1.2.rar

    这个版本包含了 Commons Logging 库的所有源码、编译后的 JAR 文件以及可能的文档和示例。Commons Logging 是 Apache 软件基金会的一个项目,它允许开发者在不改变代码的情况下切换到不同的日志框架,如 Log4j、Java...

    (zt)Commons-logging + Log4j 入门指南

    3. 使用Commons-Logging:在代码中,通过引入`org.apache.commons.logging.Log`和`org.apache.commons.logging.LogFactory`,你可以创建并使用日志对象。例如: ```java import org.apache.commons.logging.Log; ...

    commons-logging-1.1.1,DWR,jstl

    通过阅读Apache Commons Logging的源码,你可以了解到它是如何实现日志接口的封装;查看DWR的源码,可以理解其如何实现服务器到客户端的数据推送;而研究JSTL的源码,则有助于你掌握如何在JSP中更高效地使用标签库。...

    Java日志学习一:Log4j和commons-logging的关系

    commons-logging通过简单的API调用,如`org.apache.commons.logging.LogFactory.getLog(Class)`,就能获取到相应的日志实现。 在实际应用中,如果你的项目使用了commons-logging,它会自动查找可用的日志实现,Log4...

    commons-logging的源码和jar包

    源码分析: 1. **模块化设计**:Commons Logging 提供了一个统一的 API,它定义了一些基本的日志操作,如 `Log` 接口,其中包含 `debug()`, `info()`, `warn()`, `error()` 和 `fatal()` 等方法。通过这个接口,...

    commons-logging-1.1.3.rar

    通过分析 Commons Logging 的源码,开发者可以了解到其查找和选择日志实现的策略,例如如何通过系统属性、类路径查找、服务提供者接口(SPI)等方式来确定实际的日志实现。此外,还可以学习到如何利用动态代理技术来...

    slf4j+logback 于log4j+commons-logging大PK

    Commons-Logging是Apache基金会的一个项目,它提供了一个抽象层,允许在多个日志框架之间进行选择。虽然初衷是为了提供便利,但由于其内部实现的复杂性和一些已知的问题,如类加载器冲突,Commons-Logging在某些情况...

    日志框架学习之一:commons-logging+log4j

    标题中的“日志框架学习之一:commons-logging+log4j”揭示了本文将探讨的是在Java开发中常用的两个日志处理工具——Apache Commons Logging和Log4j。这两个框架是日志记录的基础,广泛应用于各种Java应用程序,为...

    Commons Logging 源码解析一

    Commons Logging是Apache软件基金会开发的一个轻量级的日志记录工具包,它是Java日志框架的一个抽象层。这篇博文“Commons Logging 源码解析一”可能涉及到对这个库的内部工作原理、设计模式以及如何使用的深入探讨...

    bcprov-jdk16-145.jar,commons-io-2.0.1.jar,commons-lang-2.5.jar

    7. **commons-logging.jar-master.zip**:这个文件看起来像是Apache Commons Logging库的一个源码版本。Commons Logging是Java日志抽象层,它允许开发者在应用中使用不同的日志框架(如log4j、java.util.logging等)...

    Log4j与common-logging

    标题中的“Log4j与common-logging”涉及的是两种广泛使用的Java日志框架。Log4j是Apache软件基金...文件“Apache Commons Logging日志与Log4j及JUL的区别.doc”可能包含了更深入的比较和分析,建议查阅以获取更多信息。

    commons的jar包

    8. **Commons Logging**:一个轻量级的日志接口抽象层,可以适配多种日志实现,如Log4j、Java Util Logging等。 9. **Commons HttpClient**:虽然已被废弃,但曾经是HTTP客户端操作的主要工具,现在可以使用Apache ...

    Common-log 和log4j2 配合使用

    `Common-Log`,全称为`Apache Commons Logging`,是Apache软件基金会开发的一个轻量级的日志接口,它提供了一个统一的日志API,允许开发者在不改变代码的情况下更换不同的日志实现。其核心思想是解耦日志实现和应用...

    apache-tomcat-7.0.34-src.zip

    源码分析: 1. **目录结构**:解压后,你会看到一个典型的开源项目目录结构,包括`bin`、`conf`、`lib`、`logs`、`webapps`、`work`等目录,以及`src`目录。`src`目录下进一步分为`java`和`native`子目录,分别存储...

    Java项目记录日志

    3. `commons-logging-1.1.1.jar` 和 `commons-logging-1.0.4.jar`:这两个是Apache Commons Logging的不同版本,负责提供日志接口和适配器。 在实际项目中,配置这些库通常需要编写XML配置文件,比如Log4j的`log4j....

    elasticsearch-analysis-ik-5.2.0.zip

    - commons-logging-1.2.jar:Apache Commons Logging库,提供日志记录的抽象层,方便切换不同的日志实现。 此外,plugin-descriptor.properties文件包含了插件的基本信息,如版本、描述等,用于Elasticsearch识别和...

Global site tag (gtag.js) - Google Analytics