log4j入门(转)
Log4j实在是很熟悉,几乎所有的Java项目都用它啊。但是我确一直没有搞明白。终于有一天我受不了了,定下心去看了一把文档,才两个小时,我终于搞明白了。一般情况下Log4j总是和Apache Commons-logging一起用的,我也就一起介绍吧。多了个东西不是更麻烦,而是更简单! 在Log4J中存在几个概念首先介绍一下,最最重要的两个是Logger和Appender(请参考Log4J手册),其实是继承层次以及输出控制。 首先Log4J中总是存在一个rootLogger,即使没有显示配置也是存在的,并且默认输出级别为DEBUG。
其它的logger都继承自这个rootLogger(如果其他logger未单独定义其输出级别)。
Log4J中的层次是用'.'来分隔的,如log4j.logger.com.example.test,这里并不是说log4j.logger后面一定是具体的包名乃至类名,
这个名称可以自定义,我们甚至可以定义一个log4j.logger.A.B.C, 在com.example.test中的类里取名称为A.B的logger,如
Logger logger = Logger.getLogger("A.B")
上例中我们建立了3个logger实例,它们分别是"A"、"A.B"、"A.B.C"。每次我们在系统中取得logger时,并不是新建实例,这些实例是系统启动的时候就按照配置文件初始化好的(也可能时第一次引用的时候建立的,然后缓存其实例供以后使用,这部分还没有时间研究)。 限制appender叠加性
例1:
log4j.rootLogger=DEBUG, Console
log4j.logger.A=DEBUG, Console
log4j.logger.A.B=INFO, Console
对于logger A.B输出的任何日志会往控制台输出三次,原因是A.B继承A的以及A的父logger的所有appender,
这种继承关系仅仅是把父logger的appender添加到自己的appender列表中,父logger的输出level不会影响
子logger的输出。 例2:限制appender叠加
log4j.rootLogger=DEBUG, Console
log4j.logger.A=DEBUG, Console
log4j.logger.A.B=INFO, Console
log4j.additivity.A.B=false
logger A.B的日志仅会输出到自己Console中,不会继承任何父logger的appender。 控制appender的输出级别
若想对输出到appender中的日志级别进行限制的话,就需要用到threshold来控制。
log4j.threshold=ERROR 用来控制所有的appender,即输出到所有appender的日志,
不管原来是什么级别的,都不能低于threshold所规定的级别。 log4j.appender.Console.threshold=ERROR 用来控制指定的appender的输出级别。 Log4j的简单思想 Log4j真的很简单,简单到令人发指的地步。不是要记录日志吗?那就给你一个Log,然后你用Log来写东西就行了,先来一个完整类示例: package test; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class Test { static Log log = LogFactory.getLog(Test.class); public void log(){ log.debug("Debug info."); log.info("Info info"); log.warn("Warn info"); log.error("Error info"); log.fatal("Fatal info"); } /** * @param args */ public static void main(String[] args) { Test test = new Test(); test.log(); } } 别怕,看完这篇文章你就会觉得很简单了。 Log4j默认把日志信息分为五个等级 all<debug < info < warn < error < fatal<off 虽然可以自己添加等级,但是我觉得没有必要,五个够用了吧!你要写入信息的时候就把信息归为五个等级中的一个,然后调用相应的函数即可。 分五个等级到底有什么用呢?日志信息到底写到哪里去了? “LogFactory.getLog(Test.class)”又是什么意思捏?接着往下看吧!(现在用这个Logger.getLogger(Test.class)吧) Log4j的关键之处在于它的继承思想。也就是一个Log可以继承另外一个Log的属性(输出到哪里,日志等级,日志格式等等)。怎么继承? Log4j是根据Log的名字来判断继承关系的,比如: 名字为“com.zhlmmc.lib”的Log就是“com.zhlmmc.lib.log”的parent,明白了吧!Log4j还有一个rootLogger,相当于Java的Object。 回过头来看“LogFactory.getLog(Test.class)”这里的“Test.class”事实上传进去的是Test这个类的完整路径(包名+类名),“test.Test”。这样如果存在“test”这个Log那么Test这个Log就继承它,否则就继承rootLogger。 那具体的Log属性是在哪里定义的呢? 关于logger的两点说明
用同名参数调用Logger.getLogger(String name)将返回同一个logger的引用。故可以在一个地方配置logger,在另外一个地方获得配置好的logger,而无须相互间传递logger的引用。
logger的创建可以按照任意的顺序,即,父logger可以后于子logger被创建。log4j将自动维护logger的继承树。 常见的配置文件 虽然可以用xml或者在运行时用Java来配置Log4j,但还是properties文件好用啊! log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout # Pattern to output the caller's file name and line number. log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n 分析一下: 第一行,配置log4j.rootLogger你明白吧。应为它是根,总得配置一下,否则别的Log继承什么啊。其他的Log可以配置也可以不配置。等号后面的第一个参数表示日志级别,可以填五个级别中的一种,后面的参数都是让Log知道输出到哪里,如果你想让日志输出到两个地方就加两个输出参数,比如: log4j.rootLogger=info, stdout, file 这里的info表示,该Log的日志级别为info,所有级别小于info的日志都不会被记录。比如使用这个配置文件的话,我刚开始举的那个类中 log.debug("Debug info."); 这句话是不起作用的,因为debug的级别小于info。这样就很容易控制什么信息在调试的时候要显示,什么信息在发布的时候要去掉。这些都不用改代码,很方便吧。 但,stdout和file又是什么呢? 接着往下看,就是配置stdout了,这个名字是随便取的,你可以叫它A: log4j.appender.A=org.apache.log4j.ConsoleAppender 那么上面的rootLogger的参数stdout也要改成A,其他用到的地方当然也要改。这里的关键不是名字,而是appender类型,比如这里的“ConsoleAppender”,看明白了吧,输出到Console。后面两行都是设置日志格式的,一般情况下你就照抄吧。既然是最简入门关注于理解Log4j的工作原理,我就不介绍file类型的appender了,一搜一大把。 在实际的项目开发中,很可能遇到所引用的包用Log4j来记录日志,比如Hibernate。那么在这里你可以很容易的控制这个包如何记录日志。比如在上面的配置文件中加一行: log4j.logger.org.hibernate=fatal 那么所有org.hibernate包下面的类就只会显示很少的信息,因为fatal的级别最高啊。 部署 别怕,这可不是部署Tomcat。把log4j的包和commons-logging的包(加在一起才两个)放到classpath下面。然后把配置文件保存为log4j.properties,也放在classpath下面(如果用Eclipse的话,放在src目录下即可)。然后你就可以跑了。 默认的log4j初始化过程
Logger类的静态初始化块(static initialization block)中对log4j的环境做默认的初始化。注意:如果程序员已经通过设置系统属性的方法来配置了log4j环境,则不需要再显式地调用XXXConfigurator.configure()方法来配置log4j环境了。 Logger的静态初始化块在完成初始化过程时将检查一系列log4j定义的系统属性。它所做的事情如下: 检查系统属性log4j.defaultInitOverride,如果该属性被设置为false,则执行初始化;否则(只要不是false,无论是什么值,甚至没有值,都是否则),跳过初始化。
把系统属性log4j.configuration的值赋给变量resource。如果该系统变量没有被定义,则把resource赋值为"log4j.properties"。注意:在apache的log4j文档中建议使用定义log4j.configuration系统属性的方法来设置默认的初始化文件是一个好方法。
试图把resource变量转化成为一个URL对象url。如果一般的转化方法行不通,就调用org.apache.log4j.helpers.Loader.getResource(resource, Logger.class)方法来完成转化。
如果url以".xml"结尾,则调用方法DOMConfigurator.configure(url)来完成初始化;否则,则调用方法PropertyConfigurator.configure(url)来完成初始化。如果url指定的资源不能被获得,则跳出初始化过程。 Log4j的编码习惯
让每个类都拥有一个private static的Logger对象,用来输出该类中的全部日志信息
使用xml文件来完成对log4j环境的配置。在项目的main class中的静态初始化块里放log4j环境的配置代码。注意:在一个项目中,log4j环境只需要被配置一次,而不是在每个使用了logger的类里都需要调用一次
用MyClass.class作为参数创建该类的静态Logger对象

log4j入门(转) --- 很详细 也很简单容易懂的更多相关文章

  1. 很详细、很移动的Linux makefile教程:介绍,总述,书写规则,书写命令,使用变量,使用条件推断,使用函数,Make 的运行,隐含规则 使用make更新函数库文件 后序

    很详细.很移动的Linux makefile 教程 内容如下: Makefile 介绍 Makefile 总述 书写规则 书写命令 使用变量 使用条件推断 使用函数 make 的运行 隐含规则 使用m ...

  2. CentOS7 下Docker最新入门教程 超级详细 (安装以及简单的使用)

    转载https://blog.csdn.net/wzsy_ll/article/details/82866627 1.为什么使用Docker(本人) 最近总是频繁的在新服务器发布项目, 每次发布都需要 ...

  3. Matlab绘图-很详细,很全面

    强大的绘图功能是Matlab的特点之一,Matlab提供了一系列的绘图函数,用户不需要过多的考虑绘图的细节,只需要给出一些基本参数就能得到 所需图形,这类函数称为高层绘图函数.此外,Matlab还提供 ...

  4. 很详细、很移动的Linux makefile 教程

    近期在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指南>读到makefile就越看越迷糊,可能是我的理解能不行. 于是google到了以下这篇文章.通俗易懂.然后把它贴出 ...

  5. Binding to the Most Recent Visual Studio Libraries--说的很详细,很清楚

    Every version of Visual Studio comes with certain versions of the Microsoft libraries, such as the C ...

  6. 转:Java多线程学习(总结很详细!!!)

    Java多线程学习(总结很详细!!!) 此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢? 本文主要讲java中多线程 ...

  7. [转]Java多线程学习(总结很详细!!!)

    Java多线程学习(总结很详细!!!) 此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢? 本文主要讲java中多线程 ...

  8. ETL讲解(很详细!!!)

    ETL讲解(很详细!!!) ETL是将业务系统的数据经过抽取.清洗转换之后加载到数据仓库的过程,目的是将企业中的分散.零乱.标准不统一的数据整合到一起,为企业的决策提供分析依据. ETL是BI项目重要 ...

  9. 很详细的SpringBoot整合UEditor教程

    很详细的SpringBoot整合UEditor教程 2017年04月10日 20:27:21 小宝2333 阅读数:21529    版权声明:本文为博主原创文章,未经博主允许不得转载. https: ...

随机推荐

  1. 从零开始学习R语言(二)——数据结构之“因素(Factor)”

    本文首发于知乎专栏:https://zhuanlan.zhihu.com/p/60101041 也同步更新于我的个人博客:https://www.cnblogs.com/nickwu/p/125370 ...

  2. Selenium系列(四) - 鼠标、键盘操作详细解读

    如果你还想从头学起Selenium,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1680176.html 其次,如果你不懂前端基础知识, ...

  3. 洛谷3388 tarjan割点

    题目链接:https://www.luogu.com.cn/problem/P3388 tarjan算法果然牛逼,时间复杂度是O(|V|+|E|),所以1e4个结点2e5条边的图完全不在话下orz o ...

  4. 写爬虫爬了3w条职位数据,看看当前招聘形势 | 开源

    最近有不少程序员又开始找工作了,为了了解目前技术类各职位的数量.薪资.招聘公司.岗位职责及要求,我爬取了拉勾网北上广深4个城市的招聘数据,共3w条.职位包括:人工智能(AI).大数据.数据分析.后端( ...

  5. 最简单的 TensorFlow 代码,TensorFlow Hello World 。

    # -*- coding:utf-8 -*- from __future__ import print_function ''' HelloWorld example using TensorFlow ...

  6. 深度学习vs机器学习 | 这些本质区别你知道多少?

    目录: 数据相关性 硬件依赖性 特征工程 解决问题方法 执行时间 可解释性 一.数据相关性 深度学习与传统机器学习最重要的区别是,随着数据量的增加,其性能也随之提高.当数据很小的时候,深度学习算法并不 ...

  7. 用一个例子说说gRPC的四种服务方法

    本文通过一个简单的例子来演示这4种类型的使用方法 案例代码:https://github.com/codeAB/grpc-sample-example 目录结构说明 ├── calculator.pr ...

  8. Java系列之内部类

    今天温习一下 Java 中的内部类,内部类一般有如下几种:静态内部类.成员内部类.匿名内部类和方法内部类,下文中将主要介绍静态内部类和成员内部类,主要内容如下: 概述 静态内部类 成员内部类 匿名内部 ...

  9. 监控一哥Prometheus你可认识?

    先大致认识认识普罗米修斯 —— Prometheus. 依据官方文档https://prometheus.io/docs/introduction/overview/ 大概能够了解到 Promethe ...

  10. Java基础知识1-Java简介

    Java语言技术架构 JAVASE:(Java platform to Standard Edition)标准版,用于桌面级应用开发. JAVAME:(Java plataform to Micro ...