log4j系列一:log4j简介以及Loggers

来源:互联网 发布:天津外国语大学 知乎 编辑:程序博客网 时间:2024/05/01 06:01

简介

经验表明,在项目中使用日志是有很多益处的。譬如查看bug、查看应用执行的记录等。但是他也是有缺点的,典型的就是拖慢了应用系统响应的时间。

在平时开发中,任何一个中小型的项目可能都会采用自己的日志记录方式,最著名的就是System.out.println这种类似的。但是在大型的商务系统中,采用System.out.println很明显不能满足系统的需求。log4j就是在这样的情形下诞生的。

log4j是一个成熟的日志系统。经历过了1.x时代,目前我们主要使用的都是2.x,1.x至2015年8月5日起不在维护。到目前为止,log4j已被引用到C、C++、C#、Perl、Python等语言中。在此我们主要介绍Java系的。

log4j中最主要的几个概念分别是Loggers(记录器)、Appenders(输出源)和Layouts(布局器)。可分别理解为日志类别,日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。

首先我们来介绍Loggers。

Loggers

Logger结构

Loggers其实就是一些命名的实体。在log4j中,创建的方式为:

public class App {    private static final Logger log = LoggerFactory.getLogger(App.class);}

之后,log4j会将创建的Logger实例保存在一个ConcurrentMap中。以上面的代码为例,key则为App.class.getName(),value则为log实例。从这里可以看出,Logger的名字是大小写敏感的,如果key不同,则之后获取到的Logger实例则不同。Logger的名字一般为类的全限定名,当然你也可以自己指定,因为它的构造函数中可以用String来指定,但是务必要清晰明了。

log4j定义了一套结构,即一个logger A的名字为另一个logger B的名字+“.”构成的话,则B是A的祖先。如果B和A之间没有其他的logger的话,则B是A的父亲。但是,不管如何,任何一个logger都有一个共同的祖先叫root,且root是原始祖先,你不能根据名称来获取root Logger,但是你可以采用Logger.getRootLogger()来获得它。

例如,indi.latchindi.latch.training的祖先,明确的说是它的父亲。再比如说,javajava.util的父亲,是java.util.Vector的祖先。

Logger优先级

为了能更好的控制日志输出,log4j还提供了Logger的优先级。常见的级别有DEBUG、INFO、WARN、ERROR和FATAL(你也可以定义自己的级别)。其级别关系为DEBUG < INFO < WARN < ERROR < FATAL

Logger的优先级是可以传递的。如果指定的一个Logger没有赋值优先级,则会从其最近的具有优先级的祖先中获取优先级,直至到root。

以下展示了四种赋值不同优先级及获取优先级的情况:

表1:只有root具有优先级,那么其子Logger都会继承root的优先级。

Logger名称 赋值优先级 继承优先级 root Proot Proot indi none Proot indi.latch none Proot indi.latch.training none Proot

表2:各个Logger都具有自己的优先级,则无需获取其祖先类优先级

Logger名称 赋值优先级 继承优先级 root Proot Proot indi P1 P1 indi.latch P2 P2 indi.latch.training P3 P3

表3:indi.latch的Logger没有优先级,其父亲具有优先级,则从其父亲indi中获取

Logger名称 赋值优先级 继承优先级 root Proot Proot indi P1 P1 indi.latch none P1 indi.latch.training P3 P3

表4:indi.latch和indi.latch.training的Logger没有优先级,则其最近具有优先级的祖先indi中获取

Logger名称 赋值优先级 继承优先级 root Proot Proot indi P1 P1 indi.latch none P1 indi.latch.training none P1

log4j的优先级可以控制日志的输出。这很重要,因为log4j只会输出级别高于或等于设定级别的日志。Logger日志输出常见的方法如下:

package org.apache.log4j;  public class Logger {    // Creation & retrieval methods:    public static Logger getRootLogger();    public static Logger getLogger(String name);    // printing methods:    public void trace(Object message);    public void debug(Object message);    public void info(Object message);    public void warn(Object message);    public void error(Object message);    public void fatal(Object message);    // generic printing method:    public void log(Level l, Object message);}

debug即表示采用DEBUG级别输出日志;info表示采用INFO级别输出,其他依次类推。

最后我们给出一个设置优先级和采用优先级输出的小例子:

public class App {    // 获取一个命名为indi.latch的Logger    private static final Logger  logger = Logger.getLogger("indi.latch");    // 获取一个命名为indi.latch.training的Logger    private static final Logger trainLogger = Logger.getLogger("indi.latch.training");    public static void main( String[] args ) {        //加载基本的配置(后面会讲解)        BasicConfigurator.configure();        //设置indi.latch Logger的优先级为INFO        logger.setLevel(Level.INFO);        // 这次日志会输出,因为WARN>INFO        logger.warn("Low fuel level.");        //这次日志不会输出,因为DEBUG<INFO        logger.debug("Starting search for nearest gas station.");        //这次日志会输出。因为trainLogger会获取logger的优先级,即INFO        trainLogger.info("Located nearest gas station.");        //这次日志不会输出。因为trainLogger会获取logger的优先级,即INFO,但是DEBUG<INFO        trainLogger.debug("Exiting gas station search");    }}
2 0
原创粉丝点击