commons.logging1.1.1源代码研究(4)-- JDK14Logger实现

一、对于java.util.logging的介绍

http://gceclub.sun.com.cn/Java_Docs/jdk6/html/zh_CN/api/java/util/logging/package-summary.html

1.自从jdk1.4才引入logging包

2.包结构分析

总体结构图

从以上总体结构图中可以看出以下几点:

a.LogManager创建并维护Logger的实例,同时LogManager也指定日志配置属性

b.Logger指定了某一日志层次Level

c.Logger包含了一个或多个Handler

d.Handler使用Formatter来格式化LogRecord

e.当Logger发送LogRecord到Handler时,会利用Filter来检查是否此日志记录满足条件

f.Logger中保留有Filter

g.Handler中保留有Filter

 

Handler关系

commons.logging1.1.1源代码研究(4)-- JDK14Logger实现_第1张图片

 

有几种Handler用于处理LogRecord记录

a.ConsoleHandler  发送到控制台日志

b.FileHandler  发送到文件

c.MemoryHandler 缓冲到内存中

d.SocketHandler  向Socket发送的处理

e.StreamHandler 基于流的日志处理

 

Formatter关系

SimpleFormatter  简单格式化

XMLFormatter  XML格式化

 

设计的优点:

1).添加新的处理者十分容易(假如要将日志记录到DB中,可以写一个DBHandler类继承Handler类)

2).添加新的日志格式十分容易,只需要添加新的Formatter实现类即可

 

3.主要的类介绍

Level  --  表示日志的层次

各级别按降序排列如下:

  • SEVERE(最高值)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST(最低值)
  • ALL
  • OFF

Logger  --  用于记录日志

     大多数 logger 输出方法都带有 "msg" 参数。此 msg 参数可以是一个原始值,也可以是一个本地化的键。在格式化期间,如果 logger 具有(或继承)一个本地化 ResourceBundle,并且 ResourceBundle 包含 msg 字符串的映射关系,那么用本地化值替换 msg 字符串。否则使用原来的 msg 字符串。

日志记录方法划分为 5 个主要类别:

  • 一系列的 "log" 方法,这种方法带有日志级别、消息字符串,以及可选的一些消息字符串参数。

  • 一系列的 "logp" 方法(即 "log precise"),其与 "log" 方法相似,但是带有显式的源类名称和方法名称。

  • 一系列的 "logrb" 方法(即 "log with resource bundle"),其与 "logp" 方法相似,但是带有显式的在本地化日志消息中使用的资源包名称。

  • 还有跟踪方法条目("entering" 方法)、方法返回("exiting" 方法)和抛出异常("throwing" 方法)的便捷方法。

  • 最后,还有一系列在非常简单的情况下(如开发人员只想为给定的日志级别记录一条简单的字符串)使用的便捷方法。这些方法按标准级别名称命名("severe"、"warning"、"info" 等等),并带有单个参数,即一个消息字符串。

Logger 上执行的所有方法都是多线程安全的。

二、主要代码分析

以下是JDK14Logger用来记录日志的一段代码:

private void log( Level level, String msg, Throwable ex ) { Logger logger = getLogger(); if (logger.isLoggable(level)) { // Hack (?) to get the stack trace. Throwable dummyException=new Throwable(); StackTraceElement locations[]=dummyException.getStackTrace(); // Caller will be the third element String cname="unknown"; String method="unknown"; if( locations!=null && locations.length >2 ) { StackTraceElement caller=locations[2]; cname=caller.getClassName(); method=caller.getMethodName(); } if( ex==null ) { logger.logp( level, cname, method, msg ); } else { logger.logp( level, cname, method, msg, ex ); } } }

其中:为什么选locations[2]呢?比如:我的程序调用了debug用于记录异常日志,则调用链为:

YourApp->Logger.debug->Logger.log,则栈顶为Logger.log,为了记录是哪个类出的异常,所以应为locations[2]

 

另外,Jdk13LumberjackLogger实现基本上同于 JDK14Logger实现

你可能感兴趣的:(jdk,多线程,String,null,logging,代码分析)