`
kalogen
  • 浏览: 880144 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

log4j和common-logging的区别

    博客分类:
  • Java
阅读更多

Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输出地;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。那么是不是这样,我们就可以完全使用log4j,而不需要扩展定制了呢?

1、基本介绍Log4j

  Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输出地;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

  log4j的好处在于:

  1) 通过修改配置文件,就可以决定log信息的目的地——控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等

  2) 通过修改配置文件,可以定义每一条日志信息的级别,从而控制是否输出。在系统开发阶段可以打印详细的log信息以跟踪系统运行情况,而在系统稳定后可以关闭log输出,从而在能跟踪系统运行情况的同时,又减少了垃圾代码(System.out.println(......)等)。

  3) 使用log4j,需要整个系统有一个统一的log机制,有利于系统的规划。

  那么是不是这样,我们就可以完全使用log4j,而不需要扩展定制了呢?当然不是这样,因为每个项目的需求不一样,而且log4j本身也提供了灵活的扩展机制。下面我们说说log4j常用的扩展方式。

2、扩展点Log4j

2.1 自己的日志系统

  每一个项目都想有自己的一套日志系统,而不受其他项目、jar包的影响。所以日志系统需要独立存在,且有相应的自己单独的配置文件而不受影响。我们先来看看common-logging和log4j的默认工作流程:

  common-logging

  当我们用Log log = LogFactory.getLog(“loggerName”);取得log时,让我们看看他是如何工作的?
  1)、首先在classpath下寻找自己的配置文件commons-logging.properties,如果找到,则使用其中定义的Log实现类
  2)、如果找不到commons-logging.properties文件,则在查找是否已定义系统环境变量org.apache.commons.logging.Log,找到则使用其定义的Log实现类
  3)、查看classpath中是否有Log4j的包,如果发现,则自动使用Log4j作为日志实现类
  4)、使用JDK自身的日志实现类(JDK1.4以后才有日志实现类)
  5)、使用commons-logging自己提供的一个简单的日志实现类SimpleLog

  commons-logging总是能找到一个日志实现类,并且尽可能找到一个"最合适"的日志实现类.
  .可以不需要配置文件
    .自动判断有没有Log4j包,有则自动使用之
    .最悲观的情况下也总能保证提供一个日志实现(SimpleLog)

  log4j

  当我们用Logger.getLogger(loggerName);取得log时,让我们看看他是如何工作的?
  1)、查找是否已定义系统环境变量log4j.configuration,找到则使用其定义的Log配置文件;否则搜索log4j.xml,如果存在,则执行4)
  2)、如果不存在,搜索log4j.properties
  3)、如果不存在,则使用程序默认的日志仓库
  4)、如果存在,注册配置日志仓库
  5)、去日志仓库中查询,如果不存在,则new一个
 
  从上面我们可以看到无论是common-logging还是log4j,以及其他的日志开源系统都会提供一套默认的遍历规则,去搜索他的log记录实例。一般情况下,我们都会使用它的默认规则,但是这样的话,我们就会受制于它,比如如果有人在默认规则中改变了某一个条件。
如果我们不想使用它的默认规则,该怎么办?很简单,在log4j中是通过日志仓库来维护一套独立日志系统,只要我们直接使用它的日志仓库,写一个我们自己的日志工厂就可以了。具体如下:

Public final class CustomLogFactory {
 //日志仓库实例
 Static LoggerRepository h = new Hierarchy(new RootLogger(Level.DEBUG));

 Static {
  //配置文件定制日志仓库属性,这里面你可以做更多的文章
  //来定义自己的配置文件位置等等
  new PropertyConfigurator().configure(h, urlConfigFile);
 }

 public static Logger getLogger(String loggerName) {
  return h.getLogger(loggerName);
 }
}

  这样你的日志系统完全独立了。是不是很容易?

2.2 自己的日志记录器

  Log4j的logger本身提供八种级别的日志记录,如果你想让你的logger没有级别概念,或者让日志信息支持国际化,那该怎么办?

  Log4j用于第三方扩展的记录日志方法API

public boolean isEnabledFor(Priority level);
public void log(String callerFQCN, Priority level, Object message, Throwable t);

  扩展示例

  1)、没有级别概念

Public final class CustomLogger {
 //log4j日志记录器
 Logger log4j;
 
 //自己的FQCN
 Private static final String FQCN = CustomLogger.class.getName();
 
 //构造方法
 Private CustomLogger(String loggerName) {
  log4j = CustomLogFactory.getLogger(loggerName);
 }
 
 //工厂方法
 Public static CustomLogger getLogger(String loggerName) {
  Return new CustomLogger(loggerName);
 }
 
 Public Boolean isEntryEnabled() {
  Return log4j. isEnabledFor(Level.INFO);
 }

 //程序入口日志
 //你完全可以在message上做些手脚,加上一些自己的特殊的日志信息
 //当然你也可以后面介绍的Appender的时候加
 Public void entry(String message, Throwable t) {
  Log4j.log(FQCN , Level.INFO, message, t);
 }
 
 Public Boolean isExitEnabled() {
  Return log4j. isEnabledFor(Level.INFO);
 }

 //程序结束日志
 Public void exit(String message, Throwable t) {
  Log4j.log(FQCN , Level.INFO, message, t);
 }
}

  2)、支持国际化

  主要是在message取得上做点事情。就像上面那个Public void entry(String message, Throwable t);如果你把API改为Public void entry(String messageID, Throwable t);实现改为:

Public void entry(String messageID, Throwable t) {
 Log4j.log(FQCN , Level.INFO, getMessage(messageID), t);
}

//取得相应的国际化信息
Private String getMessage(String messageID) {
 Return InternalResource.getLogMessage(messageID, Locale.getDefault());
}

2.3 自己的日志输出地

  Log4j本身提供了大量的默认Appender实现,已经能很好的解决大部分应用,但是有时候我们还是有一些自己的需要,比如只有在输出到控制台Appender时加一个运行时才能确定的固定前缀。我们可以这么写:

public final class CustomConsoleAppender extends org.apache.log4j.ConsoleAppender {
 
 @Override
 protected void subAppend(LoggingEvent event) {
  StringBuffer msgBuf = new StringBuffer();
 
  //固定前缀
  msgBuf.append('[');
  msgBuf.append(Manager.current ().getName());
  msgBuf.append(']');
 
  //根据配置文件中的格式化信息格式化event
  msgBuf.append(this.layout.format(event));
  this.qw.write(msgBuf.toString());
  ……
 }
}

  也就是我们想定制某一种日志输出地,直接继承相应的log4j中的类似的Appender,然后复写相应的方法即可。最后在配置文件中使用自己定义的Appender类就行了。

2.4 自己的日志过滤器

  Log4j的日志输出控制级别比较中有一个缺陷就是只能大于某个级别时才能输出,没有小于某个级别时才输出的控制,当然一般不会用到,如果有类似这样的需求是不是就做不到了呢?不是的,这时候你可以使用日志过滤器来实现。比如有这样一个需求,输出到控制台的日志信息,当级别小于WARN时,用 System.out;当大于等于WARN时,用System.err。

  过滤器定义如下:

public final class CustomWarnLevelFilter extends org.apache.log4j.spi.Filter {
 @Override
 public int decide(LoggingEvent event) {
  //大于等于WARN的日志不允许输出
  if(event.getLevel().toInt() >= Level. WARN.toInt()) {
   return DENY;
  } else {
   return ACCEPT;
  }
 }
}

 
  配置文件中可以这样配置:

<appender class="com.primeton.ext.common.log.EOSConsoleAppender" name="CONSOLE_OUT">
 <param name="Target" value="System.out"/>
 <layout class="org.apache.log4j.PatternLayout">
  <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss,SSS}][%p][%C][Line:%L] %m%n"/>
 </layout>
 <filter class=" CustomWarnLevelFilter "/>
</appender>
 
<appender class="com.primeton.ext.common.log.EOSConsoleAppender" name="CONSOLE_ERR">
 <param name="Target" value="System.err"/>
 <param name="Threshold" value="WARN"/>
 <layout class="org.apache.log4j.PatternLayout">
  <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss,SSS}][%p][%C][Line:%L] %m%n"/>
 </layout>
</appender>
 
<root>
 <level value="DEBUG"/>
 <appender-ref ref="CONSOLE_OUT"/>
 <appender-ref ref="CONSOLE_ERR"/>
</root>

   因为log4j设计的灵活性,所以当然也有其他的方式来达到这个目的。

  上面简单介绍了对log4j常用的扩展方式,你还可以扩展像layout、errorhandler等等,这里不再赘述。

3、性能影响因素Log4j

  Log4j一直被人所诟病的也就是它的性能问题了,所以在这里简要的说明一下使用log4j的注意事项:
  1)、如果你的日志实例的名称不是经常变化,请将它定义为static变量。
  2)、如果你的message构造很复杂,那么在构造之前,请先使用isXXXEnabled()判断。
  3)、配置文件中格式控制如果不需要,尽量不要输出类名和行号。
  4)、根据log4j的级别判断控制流程,在配置文件中尽可能配置的比较细致。
    Logger.info(message)的比较流程:
    a. 比较日志仓库的threashold
    b. 与自身的有效Level(没有则是父亲的)比较
    c. 与Appender的threashold比较
    d. 询问Appender的filter
    e. Layout格式化
    f. 记录日志
  5)、如果Appender是文件类型,请不要把文件大小设的太小。至少设为10MB(<param name="MaxFileSize" value="10MB"/>)。
  6)、如果不是即时调试程序,把你的级别设定为高级别,最好是threshold=INFO之上。
  7)、如果不是想即时看到日志信息,你也可以把Appender的ImmediateFlush 设为false(<param name="ImmediateFlush" value="false"/>)。
 
4、附录

4.1 Log4j基本概念

  Log4j体系结构图

0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" alt="查看更多精彩图片" src="http://photo9.hexun.com/p/2007/1218/156124/b_EB8A06E68A5988C607B3578E2B321942.jpg" border="0">


  日志仓库(或者容器)loggerRepository:跟一个配置文件相对应,顾名思义,里面存放着日志实例。
  1)、属性:threashold(阈值)
  2)、默认实现:org.apache.log4j.Hierarchy
  3)、日志系统━日志仓库━配置文件

 

  日志记录器:根日志和子日志(继承的概念,用“.”来区分,日志名称的重要性)
  1)、的概念(用于第三方封装和继承)FQCN
  2)、属性:level, appender, additivity(是否继承父日志的appender)

  Level:日志级别

  Appender:日志输出端
  属性:threashold(阈值),filter,Layout,Filter,ErrorHandler

0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" alt="查看更多精彩图片" src="http://photo9.hexun.com/p/2007/1218/156127/b_D1FCF6C3B6699D685976ACEF3ED1BF03.jpg" border="0">

  Layout:布局(输出格式)

0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" alt="查看更多精彩图片" src="http://photo9.hexun.com/p/2007/1218/156131/b_E0A8B726EAE0B8A4DFD8E07F2EFBCFA3.jpg" border="0">


  Filter:过滤器

0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" alt="查看更多精彩图片" src="http://photo9.hexun.com/p/2007/1218/156133/b_AAF659D42476F0763BF50CE313E3F7C4.jpg" border="0">


  ErrorHandler:错误处理器   

0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" alt="查看更多精彩图片" src="http://photo9.hexun.com/p/2007/1218/156134/b_0DC7B2D28C7407BA4D87C303AD0CA99B.jpg" border="0">
分享到:
评论

相关推荐

    Log4j与common-logging

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

    slf4j+logback 于log4j+commons-logging大PK

    今天我们将聚焦两个流行的日志框架——SLF4J(Simple Logging Facade for Java)和Logback,以及它们与Log4j和Commons-Logging的对比。 SLF4J是一个接口层的日志框架,它提供一个统一的API,允许用户在运行时插入...

    log4j.jar以及common-logging.jar两个jar文件全在这

    在实际应用中,如果`log4j.jar`和`commons-logging.jar`一起使用,通常需要确保`commons-logging`的配置指向`log4j`作为其底层实现,以充分利用`log4j`的功能和灵活性。 总结,`log4j.jar`和`commons-logging.jar`...

    log4j.jar和common-logging.jar两个都有

    本文将深入探讨`log4j.jar`和`common-logging.jar`这两个著名的Java日志库,以及它们在Java应用中的作用。 首先,`log4j.jar`是由Apache软件基金会开发的日志框架,它是Log4j项目的组成部分。Log4j是Java平台上的一...

    commons-logging-1.1.3.jar

    common-logging是apache提供的一个通用的日志接口。用户可以自由选择第三方的...使用它的好处就是,代码依赖是common-logging而非log4j, 避免了和具体的日志方案直接耦合,在有必要时,可以更改日志实现的第三方库。

    common-logging库 完整版 jar包 Eclipse

    4. **配置日志实现**:`common-logging`通过查找类路径中的特定文件(如`log4j.properties`或`logging.properties`)来确定使用哪个日志实现。如果没有找到,它会默认使用`java.util.logging`。如果你希望使用其他...

    Common-log 和log4j2 配合使用

    将`Common-Log`与`log4j2`结合使用,首先需要在项目中引入`Common-Log`的接口库和`log4j2`的实现库。在Maven项目中,可以在pom.xml文件中添加以下依赖: ```xml &lt;groupId&gt;commons-logging &lt;artifactId&gt;commons...

    用maven + spring mvc +JDBCTEMPLATE +由Slf4j实现Common-Logging+Log4j的日志控制(数据库用MySQL)

    4. **Slf4j** - 日志门面,允许用户在运行时选择不同的日志实现,如Common-Logging或Log4j,提供了统一的API进行日志记录。 5. **MySQL** - 常用的关系型数据库管理系统,用于存储应用的数据。 在搭建项目时,首先...

    common-logging1.1.1jar

    通过抽象出一个通用的日志接口,开发人员可以在运行时选择不同的日志实现,如log4j、java.util.logging或者Apache Log4j等,而无需修改代码。这使得项目具有更好的灵活性和可移植性。 在Commons Logging 1.1.1中,...

    commons-logging-1.2jar工具

    在Java社区中,有多个日志实现,如log4j、java.util.logging(JUL)和Logback等。这些实现各有特点,但它们的API并不兼容,这给开发者在不同日志系统间切换带来了困难。Commons Logging通过提供一个统一的API,使得...

    commons-logging-1.0.4.zip

    这个库的主要目标是为Java应用程序提供一个简单、统一的接口来使用各种日志框架,如log4j、Java内置的日志API(java.util.logging)或简单的控制台输出。在本文中,我们将深入探讨Commons Logging的核心概念、主要...

    Apache Commons-logging使用实例

    * 部署日志器:下载 commons-logging.jar 和 log4j.jar 包,能后把它们放到工程的 lib 目录下,引入工程中。 * 指定日志器:在属性文件 common-logging.properties 中设置实现接口的类。例如,设置 Log4j 为所使用的...

    Common Logging的jar包.zip

    Commons Logging通过提供一个抽象层,允许开发者使用简单的API来记录日志,而具体的日志实现(如Log4j、Java Util Logging或SLF4J)可以根据项目需求或者环境配置进行选择和切换。 Commons Logging的核心概念包括...

    commons-logging.jar 版本1.2

    Commons Logging提供了统一的日志接口,使得开发者能够在不修改代码的情况下切换不同的日志实现,如Log4j、java.util.logging(JUL)或Apache Logkit等。这种灵活性使得项目在不同环境下的日志配置更加方便,降低了...

    apache-log4j-2.3 核心jar包

    **log4j-api-2.x 和 log4j-core-2.x是必须的,其他包根据需要引入, Common Logging Bridge: log4j-jcl-2.3 Log4j 2是log4j 1.x和logback的改进版,据说采用了一些新技术(无锁异步、等等),使得日志的吞吐量、性能...

    commons-logging-1.0.3.jar

    用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。当然,common-logging内部有一个Simple logger的...

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

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

    commons-logging.jar

    Commons Logging (JCL)提供的是一个日志(Log)接口(interface),同时兼顾轻量级和不依赖于具体的... Because we use commons-logging you are free to choose your logging implementation (Log4j is a common choice).

    log4jappender配置kafka使用的jar包

    你需要`log4j-api.jar`和`log4j-core.jar`。 2. **Kafka生产者库**:Log4jAppender需要使用Kafka的生产者API来发送日志到Kafka集群。这通常指的是`kafka-clients.jar`。 3. **特定的Log4j-Kafka适配器**:为了使...

Global site tag (gtag.js) - Google Analytics