在用springmvc开发项目的时候,在日志管理这一块,我们一般用的都是log4j进行日志管理,但是我们在导入spring相关的jar的时候,都会看到commons-logging.jar包,为什么我们使用log4j的同时还要引入commons-logging.jar包,它们到底是一种什么关系呢?

  接下来我们看看commons-logging中的org.apache.commons.logging.Log的源码

/*** Eclipse Class Decompiler plugin, copyright (c) 2016 Chen Chao (cnfree2000@hotmail.com) ***/
package org.apache.commons.logging; public abstract interface Log {
public abstract void debug(Object paramObject); public abstract void debug(Object paramObject, Throwable paramThrowable); public abstract void error(Object paramObject); public abstract void error(Object paramObject, Throwable paramThrowable); public abstract void fatal(Object paramObject); public abstract void fatal(Object paramObject, Throwable paramThrowable); public abstract void info(Object paramObject); public abstract void info(Object paramObject, Throwable paramThrowable); public abstract boolean isDebugEnabled(); public abstract boolean isErrorEnabled(); public abstract boolean isFatalEnabled(); public abstract boolean isInfoEnabled(); public abstract boolean isTraceEnabled(); public abstract boolean isWarnEnabled(); public abstract void trace(Object paramObject); public abstract void trace(Object paramObject, Throwable paramThrowable); public abstract void warn(Object paramObject); public abstract void warn(Object paramObject, Throwable paramThrowable);
}

  很显然,commons-logging中j的log类就是一个接口,只要实现了该接j它口,那么它就是一个logger组件,继续看commons-logging下的org.apache.commons.logging.impl.Log4JLogger源码

/*** Eclipse Class Decompiler plugin, copyright (c) 2016 Chen Chao (cnfree2000@hotmail.com) ***/
package org.apache.commons.logging.impl; import java.io.Serializable;
import java.lang.reflect.Field;
import org.apache.commons.logging.Log;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority; public class Log4JLogger implements Log, Serializable {
private static final long serialVersionUID = 5160705895411730424L;
private static final String FQCN = Log4JLogger.class.getName(); private volatile transient Logger logger = null;
private final String name;
private static final Priority traceLevel; public Log4JLogger() {
this.name = null;
} public Log4JLogger(String name) {
this.name = name;
this.logger = getLogger();
} public Log4JLogger(Logger logger) {
if (logger == null) {
throw new IllegalArgumentException(
"Warning - null logger in constructor; possible log4j misconfiguration.");
} this.name = logger.getName();
this.logger = logger;
} public void trace(Object message) {
getLogger().log(FQCN, traceLevel, message, null);
} public void trace(Object message, Throwable t) {
getLogger().log(FQCN, traceLevel, message, t);
} public void debug(Object message) {
getLogger().log(FQCN, Level.DEBUG, message, null);
} public void debug(Object message, Throwable t) {
getLogger().log(FQCN, Level.DEBUG, message, t);
} public void info(Object message) {
getLogger().log(FQCN, Level.INFO, message, null);
} public void info(Object message, Throwable t) {
getLogger().log(FQCN, Level.INFO, message, t);
} public void warn(Object message) {
getLogger().log(FQCN, Level.WARN, message, null);
} public void warn(Object message, Throwable t) {
getLogger().log(FQCN, Level.WARN, message, t);
} public void error(Object message) {
getLogger().log(FQCN, Level.ERROR, message, null);
} public void error(Object message, Throwable t) {
getLogger().log(FQCN, Level.ERROR, message, t);
} public void fatal(Object message) {
getLogger().log(FQCN, Level.FATAL, message, null);
} public void fatal(Object message, Throwable t) {
getLogger().log(FQCN, Level.FATAL, message, t);
} public Logger getLogger() {
Logger result = this.logger;
if (result == null) {
synchronized (this) {
result = this.logger;
if (result == null) {
this.logger = (result = Logger.getLogger(this.name));
}
}
}
return result;
} public boolean isDebugEnabled() {
return getLogger().isDebugEnabled();
} public boolean isErrorEnabled() {
return getLogger().isEnabledFor(Level.ERROR);
} public boolean isFatalEnabled() {
return getLogger().isEnabledFor(Level.FATAL);
} public boolean isInfoEnabled() {
return getLogger().isInfoEnabled();
} public boolean isTraceEnabled() {
return getLogger().isEnabledFor(traceLevel);
} public boolean isWarnEnabled() {
return getLogger().isEnabledFor(Level.WARN);
} static {
if (!(Priority.class.isAssignableFrom(Level.class))) {
throw new InstantiationError("Log4J 1.2 not available");
} Priority _traceLevel;
try {
_traceLevel = (Priority) Level.class.getDeclaredField("TRACE").get(
null);
} catch (Exception ex) {
_traceLevel = Level.DEBUG;
}
traceLevel = _traceLevel;
}
}
/*** Eclipse Class Decompiler plugin, copyright (c) 2016 Chen Chao (cnfree2000@hotmail.com) ***/
package org.apache.commons.logging.impl; import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.logging.Log; public class Jdk14Logger implements Log, Serializable {
private static final long serialVersionUID = 4784713551416303804L;
protected static final Level dummyLevel = Level.FINE; protected transient Logger logger = null; protected String name = null; public Jdk14Logger(String name) {
this.name = name;
this.logger = getLogger();
} protected void log(Level level, String msg, Throwable ex) {
Logger logger = getLogger();
if (!(logger.isLoggable(level)))
return;
Throwable dummyException = new Throwable();
StackTraceElement[] locations = dummyException.getStackTrace(); String cname = this.name;
String method = "unknown"; if ((locations != null) && (locations.length > 2)) {
StackTraceElement caller = locations[2];
method = caller.getMethodName();
}
if (ex == null)
logger.logp(level, cname, method, msg);
else
logger.logp(level, cname, method, msg, ex);
} public void debug(Object message) {
log(Level.FINE, String.valueOf(message), null);
} public void debug(Object message, Throwable exception) {
log(Level.FINE, String.valueOf(message), exception);
} public void error(Object message) {
log(Level.SEVERE, String.valueOf(message), null);
} public void error(Object message, Throwable exception) {
log(Level.SEVERE, String.valueOf(message), exception);
} public void fatal(Object message) {
log(Level.SEVERE, String.valueOf(message), null);
} public void fatal(Object message, Throwable exception) {
log(Level.SEVERE, String.valueOf(message), exception);
} public Logger getLogger() {
if (this.logger == null) {
this.logger = Logger.getLogger(this.name);
}
return this.logger;
} public void info(Object message) {
log(Level.INFO, String.valueOf(message), null);
} public void info(Object message, Throwable exception) {
log(Level.INFO, String.valueOf(message), exception);
} public boolean isDebugEnabled() {
return getLogger().isLoggable(Level.FINE);
} public boolean isErrorEnabled() {
return getLogger().isLoggable(Level.SEVERE);
} public boolean isFatalEnabled() {
return getLogger().isLoggable(Level.SEVERE);
} public boolean isInfoEnabled() {
return getLogger().isLoggable(Level.INFO);
} public boolean isTraceEnabled() {
return getLogger().isLoggable(Level.FINEST);
} public boolean isWarnEnabled() {
return getLogger().isLoggable(Level.WARNING);
} public void trace(Object message) {
log(Level.FINEST, String.valueOf(message), null);
} public void trace(Object message, Throwable exception) {
log(Level.FINEST, String.valueOf(message), exception);
} public void warn(Object message) {
log(Level.WARNING, String.valueOf(message), null);
} public void warn(Object message, Throwable exception) {
log(Level.WARNING, String.valueOf(message), exception);
}
}

  我们看到有两个类,一个是Jdk14Logger,另一个是Log4JLogger。到这里我们应该知道,真正记录日志的是Jdk14Logger类和Log4JLogger类。而 commons-logging 把这两个(实际上,在 org.apache.commons.logging.impl 包下,commons-logging 仅仅为我们封装了 log4j 和 sun logger)记录日志的工具重新封装了一遍(Log4JLogger.java 和 Jdk14Logger.java),可以认为 org.apache.commons.logging.Log 是个傀儡,它只是提供了对外的统一接口。因此我们只要能拿到 org.apache.commons.logging.Log,而不用关注到底使用的是 log4j 还是 sun logger。正如我们经常在项目中这样写:

private static final Log logger = LogFactory.getLog(Run.class);  

  既然如此,我们的项目有两个jar包,那么我们用的是log4j 还是 Jdk14Logger呢?我们在配置spring的web.xml文件时,经常会有如下配置:

<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

   终于找到了 org.springframework.util.Log4jConfigurer,这正是 log4j 提供给我们的初始化日志的类。至此,我们终于明白了我们系统的的确确使用的是 log4j 的日志工具。

  可是问题又来了,org.apache.commons.logging.Log 和 org.apache.log4j.Logger 这两个类,通过包名我们可以发现它们都是 apache 的项目,既然如下,为何要动如此大的动作搞两个东西(指的是 commons-logging 和 log4j)出来呢?事实上,在 sun 开发 logger 前,apache 项目已经开发了功能强大的 log4j 日志工具,并向 sun 推荐将其纳入到 jdk 的一部分,可是 sun 拒绝了 apache 的提议,sun 后来自己开发了一套记录日志的工具。可是现在的开源项目都使用的是 log4j,log4j 已经成了事实上的标准,但由于又有一部分开发者在使用 sun logger,因此 apache 才推出 commons-logging,使得我们不必关注我们正在使用何种日志工具。

commons-logging.jar 和 log4j.jar 的关系的更多相关文章

  1. commons-logging 和 log4j 之间的关系

    我们在做项目时,日志的记录是必不可少的一项任务,而我们通常是使用 apache 的 log4j 日志管理工具.然而,在项目中,我们经常会看到两个 jar 包:commons-logging.jar 和 ...

  2. Taxonomy of class loader problems encountered when using Jakarta Commons Logging(转)

    Acknowledgments I would like to thank Jacob Kjome for reviewing early drafts of this document. His c ...

  3. org.apache.log4j与org.apache.commons.logging这两个包有什么区别

    apache common logging是一种log的框架接口,它本身并不实现log记录的功能,而是在运行时动态查找目前存在的日志库,调用相关的日志函数,从而隐藏具体的日志实现log4j是具体的日志 ...

  4. java传统web项目添加maven管理jar包,log4j无法正常输出日志

    本文适合1年以上编程基础的开发人员阅读,非技术创新,可作为故障排除实录参考/收藏. 背景 笔者最近在给公司一个老的web项目改造升级,项目使用springmvc+mybatis,由于项目比较久远,没有 ...

  5. 引用log4j.jar包后,出现告警

    问题现象:在引用log4j包后,使用自己导出的jar包,编译测试例代码,在启动浏览器时出现以下告警:log4j:WARN No appenders could be found for logger ...

  6. hibernate中各个jar包的含义和关系

    最基本的Hibernate3.3.2之 JAR包(必要): 包名 位置 用途 hibernate3.jar /hibernate 核心JAR包 antlr.jar /hibernate/lib/req ...

  7. spring 3.0版本以上jar包使用以及依赖关系

    本文转载自:http://blog.csdn.net/huiwenjie168/article/details/8477837 spring.jar是包含有完整发布的单个jar包,spring.jar ...

  8. java jar包 log4j不能输出解决方法

    今天运行一个jar包,jar包中使用了springContext进行加载bean和log4j配置,但是发现不能正常输入日志. 代码中增加 Xxx.class.getResource("/&q ...

  9. spring中各jar功能及jar包之间的依赖关系

    (1) spring-core.jar 这个jar文件包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心,当然你也可以在自己的应用系统中使用这些工 ...

随机推荐

  1. 2018.09.19 atcoder AtCoDeer and Election Report(贪心)

    传送门 很有意思的一道贪心. 就是每次翻最小的倍数来满足条件. 代码: #include<bits/stdc++.h> #define ll long long using namespa ...

  2. Django模型层(2)

    https://www.cnblogs.com/yuanchenqi/articles/8963244.html from django.db import models class Author(m ...

  3. jedis 链接池使用(转)

    Jedis作为redis的最佳客户端,它提供了连接池的特性,“连接池”在通常情况下可以有效的提高应用的通信能力,并且这是一种良好的设计模式.Jedis的连接池设计基于apache commons-po ...

  4. Linux命令:sed

    简介 sed 是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的 ...

  5. js级联出生日期

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. flac3d自定义变量输出云图

    定义单元体能量为微单元体的应变比能,即当应力和应变满足线性关系时,微单元体在三向应力状态下的应变比能为: (3.1) 下面代码为用户自定义云图显示变量. Flac3d Code new gen zon ...

  7. AD采样的一个例子

    用122.88k时钟采样153.6k的信号

  8. Ansible之ansible-playbook roles

    刚开始学习运用 playbook 时,可能会把 playbook 写成一个很大的文件,到后来可能你会希望这些文件是可以方便去重用的,所以需要重新去组织这些文件. 基本上,使用 include 语句引用 ...

  9. spring mvc后台如何处理ajax的请求,并返回json

    spring mvc中有一个注解:@ResponseBody,把这个注解放到ajax请求对应的@RequestMapping(xxx)方法上,在方法体内部,把要返回的json赋给一个String类型的 ...

  10. What if you are involved in an automobile accident in the US

    What if you are involved in an automobile accident in the US With increasing Chinese tourists and vi ...