log4j框架logger的继承关系以及使用场景

log4j日志框架logger是存在继承关系的,我们一般都会在log4j.properties文件中定义log4j.rootLogger。其他所有logger都继承自这个rootLooger。考虑下面这种场景:假如我们有2个类HelloLog4j和A。

  1. package aty.log;
  2. import org.apache.log4j.Logger;
  3. import aty.log.service.A;
  4. public class HelloLog4j {
  5. private static Logger logger = Logger.getLogger(HelloLog4j.class);
  6. public static void main(String[] args) {
  7. logger.debug("log in main.");
  8. new A().run();
  9. }
  10. }
  1. package aty.log.service;
  2. import org.apache.log4j.Logger;
  3. public class A {
  4. private static Logger logger = Logger.getLogger(A.class);
  5. public void run() {
  6. logger.error("log in A.java");
  7. }
  8. }

log4j.properties文件配置如下:

  1. #rootLogger can print DEBUG to console
  2. log4j.rootLogger=debug, console
  3. log4j.appender.console=org.apache.log4j.ConsoleAppender
  4. log4j.appender.console.Threshold=debug
  5. log4j.appender.console.ImmediateFlush=true
  6. log4j.appender.console.Target=System.err
  7. log4j.appender.console.layout=org.apache.log4j.PatternLayout

运行HelloLog4j.java控制台日志如下:可以看到这2个类使用的logger都是rootLogger。



现在我们有这个需求:让A.java中日志的打印到单独的a.log日志文件中,而HelloLog4j中的日志还是打印到控制台。也就是说:我们想让A和HelloLog4j这2个类使用不同的logger。java代码不用修改,我们将log4j.properties修改如下:

  1. #rootLogger can print DEBUG to console
  2. log4j.rootLogger=debug, console
  3. log4j.appender.console=org.apache.log4j.ConsoleAppender
  4. log4j.appender.console.Threshold=debug
  5. log4j.appender.console.ImmediateFlush=true
  6. log4j.appender.console.Target=System.err
  7. log4j.appender.console.layout=org.apache.log4j.PatternLayout
  8. log4j.appender.console.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%t]-[%X{ip}]-[%l]-[%p] %m%n
  9. #A.java is special.we use a individual appender for it.
  10. #A class's full qulified qualified name is logger's name.
  11. log4j.logger.aty.log.service.A=DEBUG, testA
  12. log4j.appender.testA=org.apache.log4j.FileAppender
  13. log4j.appender.testA.Threshold=warn
  14. log4j.appender.testA.ImmediateFlush=true
  15. log4j.appender.testA.Append=true
  16. log4j.appender.testA.File=c:/a.log
  17. log4j.appender.testA.layout=org.apache.log4j.PatternLayout
  18. log4j.appender.testA.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%t]-[%X{ip}]-[%l]-[%p] %m%n
  19. #avoid print to parent logger.
  20. log4j.additivity.aty.log.service.A= false

再次运行HelloLog4j可以看到:A.java中的日志并没有打印到控制台上,而是打印到了a.log文件中。



我们来解释下上面的配置:

log4j.logger.aty.log.service.A=DEBUG, testA    我们用A的全类名定义了一个logger。

log4j.additivity.aty.log.service.A= false     避免日志打印到rootLogger中。如果这里设置成true,那么A.java中的日志既会打印到控制台上,也会打印到a.log文件中。

现在我们可以介绍下logger的继承关系了,比如我们上面的类aty.log.service.A中使用了logger来写日志。那么log4j会先查找名称是"aty.log.service.A"的logger,如果没有找到,向上查找名称是"aty.log.service"的logger,如果还没有找到那么继续向上查找,查找的最顶层就是rootLogger。这就是log4j中logger的继承关系。rootLogger一定要在配置,其他特定类或者特定包的logger可以不用配置。知道了这个继承特性之后,如果我们要aty.log.dao包下所有的类都打印到同一个日志文件,那么可以进行如下配置。

  1. # a package appender
  2. log4j.logger.aty.log.dao=DEBUG, daoAppender
  3. log4j.appender.daoAppender=org.apache.log4j.FileAppender
  4. log4j.appender.daoAppender.Threshold=warn
  5. log4j.appender.daoAppender.ImmediateFlush=true
  6. log4j.appender.daoAppender.Append=true
  7. log4j.appender.daoAppender.File=c:/dao.log
  8. log4j.appender.daoAppender.layout=org.apache.log4j.PatternLayout
  9. log4j.appender.daoAppender.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%t]-[%X{ip}]-[%l]-[%p] %m%n
  10. log4j.additivity.aty.log.dao= false

可以看到:利用logger的继承特性,我们可以很容易将不同的日志打印到不同的文件中,这样可以避免各种日志混杂在一起。如果我们想将A.java中有的日志打印到a.log中,有的日志打印到控制台上也是可以的。

  1. package aty.log.service;
  2. import org.apache.log4j.Logger;
  3. public class A {
  4. private static Logger logger = Logger.getLogger(A.class);
  5. private static Logger rootLogger = Logger.getRootLogger();
  6. public void run() {
  7. logger.error("log in A.java");
  8. rootLogger.error("a to console.");
  9. }
  10. }

最后提一下:log4j默认是使用类名或者包名来查找logger的。log4j允许我们自己定义logger的名称。

  1. package aty.log.service;
  2. import org.apache.log4j.Logger;
  3. public class A {
  4. private static Logger logger = Logger.getLogger("atyAlogger");
  5. public void run() {
  6. logger.error("log in A.java");
  7. }
  8. }
  1. #use atyAlogger as appender name.
  2. log4j.logger.atyAlogger=DEBUG, testA
  3. log4j.appender.testA=org.apache.log4j.FileAppender
  4. log4j.appender.testA.Threshold=warn
  5. log4j.appender.testA.ImmediateFlush=true
  6. log4j.appender.testA.Append=true
  7. log4j.appender.testA.File=c:/a.log
  8. log4j.appender.testA.layout=org.apache.log4j.PatternLayout
  9. log4j.appender.testA.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%t]-[%X{ip}]-[%l]-[%p] %m%n
  10. #avoid print to parent logger.
  11. log4j.additivity.atyAlogger= false

一般来说,我们都是使用默认的名称,这样虽然将类名和包名在log4j.properties写死了。但是方便java类里面获取logger。因为各个类都是根据自己类的全限定名来查找logger的,具体日志到底打印到哪里去,由配置文件决定。

log4j框架logger的继承关系以及使用场景的更多相关文章

  1. Swing框架的继承关系

    ---------------siwuxie095 Java SE 8 (截止 2017/4/1 最新)在线 API 文档: http://docs.oracle.com/javase/8/docs/ ...

  2. ABP VNext框架基础知识介绍(1)--框架基础类继承关系

    在我较早的时候,就开始研究和介绍ABP框架,ABP框架相对一些其他的框架,它整合了很多.net core的新技术和相关应用场景,虽然最早开始ABP框架是基于.net framework,后来也全部转向 ...

  3. 重新想象 Windows 8 Store Apps (16) - 控件基础: 依赖属性, 附加属性, 控件的继承关系, 路由事件和命中测试

    原文:重新想象 Windows 8 Store Apps (16) - 控件基础: 依赖属性, 附加属性, 控件的继承关系, 路由事件和命中测试 [源码下载] 重新想象 Windows 8 Store ...

  4. 如何自建appender扩展Log4j框架

    1.log4j 概述 log4j 环境包括三个主要组件: logger(日志记录器):控制要启用或禁用哪些日志记录语句.可以对日志记录器指定如下级别: ALL . DEBUG . INFO . WAR ...

  5. 使用IntelliJ IDEA查看类的继承关系图形

    最近正好也没什么可忙的,就回过头来鼓捣过去的知识点,到Servlet部分时,以前学习的时候硬是把从上到下的继承关系和接口实现记得乱七八糟. 这次利用了IDEA的diagram,结果一目了然,也是好用到 ...

  6. iOS学习——iOS 整体框架及类继承框架图

    整理自:IOS 整体框架类图值得收藏 一 整体框架 在iOS开发过程中,对iOS的整理框架的了解和学习是必不可少的一个环节,今天我们就好好来了解一下iOS的整体框架.首先贴一个关于iOS的框架介绍:i ...

  7. phpstorm查看类的继承关系

    在看一些框架源码时,有些类有很多的继承或者接口,有一款神奇的帮助很重要 选中一个类文件,右键,选择diagrams->show diagrams 即可得到类的继承关系,如上右图 使用函数 fun ...

  8. java集合继承关系图

    面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式. 数组虽然也可以存储对象,但长度是固定的:集合长度是可变的,数组中可以存储基 ...

  9. MVC值提供组件ValueProvider的继承关系

    MVC请求过程中中各组件调用顺序:值提供组件(IValueProvider)->模型绑定组件(IModelBinder)->模型验证组件 值提供组件接口 public interface ...

随机推荐

  1. sql server存储过程中SELECT 与 SET 对变量赋值的区别 转自Theo

    SQL Server 中对已经定义的变量赋值的方式用两种,分别是 SET 和 SELECT. 对于这两种方式的区别,SQL Server 联机丛书中已经有详细的说明,但很多时候我们 并没有注意,其实这 ...

  2. JavaScript call 和apply 的理解

    这两个方法对于一些新手而言难耐弄清他们到底是怎么回事,对我我来讲我对call和apply的方法理解的也比较含糊.今天闲来无事准备彻底搞call和apply到底是怎么回事.本着互联网分享精神.我将我自己 ...

  3. Silverlight & Blend动画设计系列六:动画技巧(Animation Techniques)之对象与路径转化、波感特效

    当我们在进行Silverlight & Blend进行动画设计的过程中,可能需要设计出很多效果不一的图形图像出来作为动画的基本组成元素.然而在设计过程中可能会出现许多的问题,比如当前绘制了一个 ...

  4. java温故而知新(8)反射机制

    一.什么是反射机制  简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制  有些时候,我们用过 ...

  5. spring 代理

    java动态代理实现 1. Java自带的动态代理,反射生成字节码 2. Cglib调用asm生成子类 spring 中代理实现 1. 如果类实现了接口,使用java动态代理 2. 没有实现接口,使用 ...

  6. Docker简单说明

    前段时间工作需要,简单的研究了下docker.侧重点放在docker的镜像定制方面,后续会研究下k8s的使用. Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的.可移植的.自给自足的 ...

  7. JS_1

    学习JS分为哪几步: 1.学习基础语法 JS写在哪 JS输出 JS变量 JS函数 JS分支 JS循环 2.学习JS操作网页DOM树 获取Dom节点 触发Dom事件 对Dom进行修改 3.学习JS对象及 ...

  8. 如何创建一个基本JQuery的插件

    如何创建一个基本的插件 有时您希望在整个代码中提供一些功能.例如,也许你想要一个单一的方法,你可以调用一个jQuery选择,对选择执行一系列的操作.在这种情况下,您可能需要编写一个插件. 链接jQue ...

  9. Linux下C语言操作MySQL数据库

    MySQL是Linux系统下广泛使用的开源免费数据库,是Linux应用程序数据存储的首选. Ubuntu下安装 […]

  10. 回溯法最优装载问题(java)

    1.问题描述:      有一批共有 n 个集装箱要装上两艘载重量分别为 c1 和 c2 的轮船,其中集装箱 i 的重量为 w[i], 且重量之和小于(c1 + c2).装载问题要求确定是否存在一个合 ...