• 欢迎访问天天编码网站,Java技术、技术书单、开发工具,欢迎加入天天编码
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏天天编码吧
  • 我们的淘宝店铺已经开张了哦,传送门:https://shop145764801.taobao.com/

深入分析Java的内置日志API(java.util.logging)(三)

Java框架 tiantian 965次浏览 0个评论 扫描二维码

Hierarchy(日志层级体系)

虽然 Logger 对象的名称可以任意选取,但是一个 Logger 对象的名称决定了该 Logger 对象在 Logger 层级体系中所处的位置,名称中的每一个 . 都被认为是层级体系中的一个分支。

实际上,Java应用中的多个 Logger 对象是按照某种层级结构组织起来的。在我们使用 Logger 类的工厂方法 getLogger(String) 创建 Logger 对象时,必须以字符串参数的形式给出该 Logger 对象的名称。如果我们使用 “www.tiantianbianma.com” 创建一个 Logger 对象,那么该 Logger 对象 可能 会具有3个祖先 Logger 对象。整个的日志层级体系图 可能 会如下所示:

深入分析Java的内置日志API(java.util.logging)(三)

  • 读者可以通过调用 Logger 对象的 getParent() 方法获取其父级 Logger 对象。
  • 日志层级体系中 root logger 对象的名称是 "" ,在 logjdk 被装载时被自动创建。

日志层级体系中必须注意的一点是:所有的 Logger 对象(除了 root logger 对象)都必须明确地创建,日志层级体系的中间 Logger 对象并不会因为底层 Logger 对象的创建而自动创建。假设我们使用如下的一个示例代码来创建一个 Logger 对象:

Logger logger_wtc = Logger.getLogger("www.tiantianbianma.com");

如果此时调用 logger_wtc 对象的 getParent() 方法,那么返回的就是名称为 "" 的 root logger 对象。当然,Java工程师可以使用如下的代码片段来创建中间的 Logger 对象:

Logger logger_w = Logger.getLogger("www");
Logger logger_wt = Logger.getLogger("www.tiantianbianma");

如果此时再调用 logger_wtc 对象的 getParent() 方法,那么返回的就是名称为 www.tiantianbianma 的 logger_wt 对象。

完整流程

当一个日志信息被传递到一个 Logger 对象时,该 Logger 对象首先使用其 Level 对该日志信息进行过滤。如果该 Logger 对象具有 Filter 对象,接着会使用该 Filter 对象对日志信息进行再次过滤,此 Filter 对象可以遏制或者传播该日志信息。如果过滤的结果时继续传播,那么该日志信息就被转换成 LogRecord 对象并传播给该 Logger 对象的 Handler 对象。当然,如果没有设置 Filter 对象,同样是继续传播该日志信息。

当一个日志信息被 Logger 对象判别为继续传播时,该日志信息不仅被传播给该 Logger 对象的 Handler 对象,同时,该日志信息还会被传播给该 Logger 对象的祖先 Logger 对象的 Handler 对象。

  • 该日志信息会被传播给该 Logger 对象的 祖先 Logger 对象的 Handler 对象,而不仅仅该 Logger 对象的 Logger 对象的 Handler 对象。
  • 该日志信息会被直接传播给 Logger 对象和祖先 Logger 对象的 Handler 对象,该日志信息不会再经历祖先 Logger 对象的 Filter 对象。

一图胜万言,读者朋友直接对照下图理解:

深入分析Java的内置日志API(java.util.logging)(三)

为了方便各位读者朋友上机验证和实际动手练习,天天编程决定提供一个示例代码:

Logger logger_w = Logger.getLogger("www");
Logger logger_wt = Logger.getLogger("www.tiantianbianma");
Logger logger_wtc = Logger.getLogger("www.tiantianbianma.com");

logger_wt.addHandler(new ConsoleHandler());
logger_wtc.addHandler(new ConsoleHandler());

logger_w.info("msg: www");
logger_wt.info("msg: www.tiantianbianma");
logger_wtc.info("msg: www.tiantianbianma.com");

这个示例代码的输出是:

七月 17, 2017 3:17:27 下午 com.navercorp.ncp.controller.GreetingController main
信息: msg: www
七月 17, 2017 3:17:27 下午 com.navercorp.ncp.controller.GreetingController main
信息: msg: www.tiantianbianma
七月 17, 2017 3:17:27 下午 com.navercorp.ncp.controller.GreetingController main
信息: msg: www.tiantianbianma
七月 17, 2017 3:17:27 下午 com.navercorp.ncp.controller.GreetingController main
信息: msg: www.tiantianbianma.com
七月 17, 2017 3:17:27 下午 com.navercorp.ncp.controller.GreetingController main
信息: msg: www.tiantianbianma.com
七月 17, 2017 3:17:27 下午 com.navercorp.ncp.controller.GreetingController main
信息: msg: www.tiantianbianma.com
  • “信息:msg: www” 被 root logger 对象输出一次,logger_w 对象没有设置 Handler 对象;
  • “信息: msg: www.tiantianbianma” 被 root logger 对象和 logger_wt 对象分别输出一次;
  • “信息: msg: www.tiantianbianma.com” 被 root logger 对象、 logger_wt 对象和 logger_wtc 对象分别输出一次。

现在,假设我们往日志层级体系的中层 Logger 对象 logger_wt 上增加一个 Filter 对象,增加 Filter 对象的示例代码如下:

logger_wt.setFilter(new Filter() {
public boolean isLoggable(LogRecord record) {
return false;
}
});

此处增加的这个 Filter 对象会遏制所在 Logger 对象的所有日志信息,那么整个的示例代码的输出就变成:

七月 17, 2017 3:38:32 下午 com.navercorp.ncp.controller.GreetingController main
信息: msg: www
七月 17, 2017 3:38:32 下午 com.navercorp.ncp.controller.GreetingController main
信息: msg: www.tiantianbianma.com
七月 17, 2017 3:38:32 下午 com.navercorp.ncp.controller.GreetingController main
信息: msg: www.tiantianbianma.com
七月 17, 2017 3:38:32 下午 com.navercorp.ncp.controller.GreetingController main
信息: msg: www.tiantianbianma.com
  • logger_wt 上的 Filter 对象会遏制所有直接接受到的日志信息,自然不会继续向后和向上传播;
  • logger_wtc 上接受到的日志信息直接传播给 logger_wt 和 root logger 对象的 Handler,并正确输出。


天天编码 , 版权所有丨本文标题:深入分析Java的内置日志API(java.util.logging)(三)
转载请保留页面地址:http://www.tiantianbianma.com/java-logging-logjdk-three.html/
喜欢 (3)
支付宝[多谢打赏]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址