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的实例对象。
最常用的方法是getLog(Class
clazz)
可以看到方法内代码只有一行: return (getFactory().getInstance(clazz));
getInstance是个抽象方法,后面讲解。
这里解析下getFactory方法
- 获得当前线程的classloader,命名为contextClassLoader
- 根据contextClassLoader在缓存中获得logFactory,这里的缓存使用的是org.apache.commons.logging.impl.WeakHashTable,key是classloader,value是logFactory,如果在缓存中有logFactory则直接返回,没有进入下面的流程
- 读取配置文件commons-logging.properties
- 如果读到了配置文件,判断其中use_tccl属性,然后设定baseClassLoader是使用contextClassLoader还是使用加载本Class文件的那个classloader(名字为thisClassLoader)
- 下面生成logFactory,这里会有使用四种方式,依次来尝试生成。
- 将生成的logFactory缓存起来
- 返回logFactory
第5条种四种方式是:
- 通过系统属性中寻找org.apache.commons.logging.LogFactory的value值,根据值为类名生成logFactory
- 通过资源META-INF/services/org.apache.commons.logging.LogFactory,获得的值为类名生成logFactor
- 通过刚才读取的配置文件commons-logging.properties,从中获取以org.apache.commons.logging.LogFactory为key的value值,根据值为类名生成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参数),接着实例化。
如果这里affectState(createLogFromClass最后一个参数)为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.4的logging,如果再没有,就使用Lumberjack,它是为jdk1.2与1.3实现了Java日志 API,再没有,那就使用自身提供的一个log(SimpleLog)。
可以说commons-logging提供了一套简单的日志API给用户,但对于输出格式设定等问题,没有提供必要的API给用户,这点只能靠使用Log4j等更加强大的日志框架来完成,这也可能是为什么采用log4j作为最优先实现的原因吧。
项目中使用commons-logging的原因,可能是为了不与log4j死死的绑定在一起,使用commons-logging作为一个中间层,达到解耦的目的。
所以说commons-logging 的最大贡献就是为日志输出提供一个统一的接口,并且会在运行时,很方便的自动选择好日志实现系统。
顺便摘抄一段关于日志级别的信息:
确保日志信息在内容上和反应问题的严重程度上的恰当,是非常重要的。
-
fatal非常严重的错误,导致系统中止。期望这类信息能立即显示在状态控制台上。
-
error其它运行期错误或不是预期的条件。期望这类信息能立即显示在状态控制台上。
-
warn使用了不赞成使用的API、非常拙劣使用API, '几乎就是'错误, 其它运行时不合需要和不合预期的状态但还没必要称为 "错误"。期望这类信息能立即显示在状态控制台上。
-
info运行时产生的有意义的事件。期望这类信息能立即显示在状态控制台上。
-
debug系统流程中的细节信息。期望这类信息仅被写入log文件中。
-
trace更加细节的信息。期望这类信息仅被写入log文件中。
通常情况下,记录器的级别不应低于info。
也就是说,通常情况下debug的信息不应被写入log文件中。
分享到:
相关推荐
通过分析`commons-logging-1.2-src`的源码,我们可以发现Commons Logging的设计目标是提供一个轻量级、灵活的日志解决方案,使得开发者可以在不修改代码的情况下切换日志框架。它的接口设计简洁,适配性强大,是Java...
通过分析源码,开发者可以更好地理解Apache Commons Logging的工作原理,这对于自定义日志行为、调试日志问题或构建自己的日志适配器非常有帮助。同时,这也是一种学习通用设计模式和最佳实践的机会,比如工厂模式、...
在源码分析中,`LogFactory`的实现是关键。它使用`ServiceLoader`机制(自Java 6起)或通过检查系统属性、环境变量、类路径中的配置文件等方式,来找到并加载最适合的日志实现。这种灵活性使得开发者可以在部署时...
源码分析可以从以下几个方面进行: 1. **接口设计**:研究 `Log` 接口,了解不同日志级别的用法和语义。 2. **工厂模式**:探索 `LogFactory` 类,理解如何根据环境自动选择日志实现。 3. **适配器模式**:查看具体...
这个版本包含了 Commons Logging 库的所有源码、编译后的 JAR 文件以及可能的文档和示例。Commons Logging 是 Apache 软件基金会的一个项目,它允许开发者在不改变代码的情况下切换到不同的日志框架,如 Log4j、Java...
3. 使用Commons-Logging:在代码中,通过引入`org.apache.commons.logging.Log`和`org.apache.commons.logging.LogFactory`,你可以创建并使用日志对象。例如: ```java import org.apache.commons.logging.Log; ...
通过阅读Apache Commons Logging的源码,你可以了解到它是如何实现日志接口的封装;查看DWR的源码,可以理解其如何实现服务器到客户端的数据推送;而研究JSTL的源码,则有助于你掌握如何在JSP中更高效地使用标签库。...
commons-logging通过简单的API调用,如`org.apache.commons.logging.LogFactory.getLog(Class)`,就能获取到相应的日志实现。 在实际应用中,如果你的项目使用了commons-logging,它会自动查找可用的日志实现,Log4...
源码分析: 1. **模块化设计**:Commons Logging 提供了一个统一的 API,它定义了一些基本的日志操作,如 `Log` 接口,其中包含 `debug()`, `info()`, `warn()`, `error()` 和 `fatal()` 等方法。通过这个接口,...
通过分析 Commons Logging 的源码,开发者可以了解到其查找和选择日志实现的策略,例如如何通过系统属性、类路径查找、服务提供者接口(SPI)等方式来确定实际的日志实现。此外,还可以学习到如何利用动态代理技术来...
Commons-Logging是Apache基金会的一个项目,它提供了一个抽象层,允许在多个日志框架之间进行选择。虽然初衷是为了提供便利,但由于其内部实现的复杂性和一些已知的问题,如类加载器冲突,Commons-Logging在某些情况...
标题中的“日志框架学习之一:commons-logging+log4j”揭示了本文将探讨的是在Java开发中常用的两个日志处理工具——Apache Commons Logging和Log4j。这两个框架是日志记录的基础,广泛应用于各种Java应用程序,为...
Commons Logging是Apache软件基金会开发的一个轻量级的日志记录工具包,它是Java日志框架的一个抽象层。这篇博文“Commons Logging 源码解析一”可能涉及到对这个库的内部工作原理、设计模式以及如何使用的深入探讨...
7. **commons-logging.jar-master.zip**:这个文件看起来像是Apache Commons Logging库的一个源码版本。Commons Logging是Java日志抽象层,它允许开发者在应用中使用不同的日志框架(如log4j、java.util.logging等)...
标题中的“Log4j与common-logging”涉及的是两种广泛使用的Java日志框架。Log4j是Apache软件基金...文件“Apache Commons Logging日志与Log4j及JUL的区别.doc”可能包含了更深入的比较和分析,建议查阅以获取更多信息。
8. **Commons Logging**:一个轻量级的日志接口抽象层,可以适配多种日志实现,如Log4j、Java Util Logging等。 9. **Commons HttpClient**:虽然已被废弃,但曾经是HTTP客户端操作的主要工具,现在可以使用Apache ...
`Common-Log`,全称为`Apache Commons Logging`,是Apache软件基金会开发的一个轻量级的日志接口,它提供了一个统一的日志API,允许开发者在不改变代码的情况下更换不同的日志实现。其核心思想是解耦日志实现和应用...
源码分析: 1. **目录结构**:解压后,你会看到一个典型的开源项目目录结构,包括`bin`、`conf`、`lib`、`logs`、`webapps`、`work`等目录,以及`src`目录。`src`目录下进一步分为`java`和`native`子目录,分别存储...
3. `commons-logging-1.1.1.jar` 和 `commons-logging-1.0.4.jar`:这两个是Apache Commons Logging的不同版本,负责提供日志接口和适配器。 在实际项目中,配置这些库通常需要编写XML配置文件,比如Log4j的`log4j....
- commons-logging-1.2.jar:Apache Commons Logging库,提供日志记录的抽象层,方便切换不同的日志实现。 此外,plugin-descriptor.properties文件包含了插件的基本信息,如版本、描述等,用于Elasticsearch识别和...