Java 利用Supplier创建日志消息

Java 利用Supplier创建日志消息,用户希望创建由日志级别(log level)控制是否可见的日志消息。使用 java.util.logging.Logger 类新增的各种日志方法,它们传入 Supplier 作为参数。目前,Logger 类中的日志方法(如 infowarningsevere 等)包括两种重载形式,一种传入单个 String 作为参数,另一种传入 Supplier<String> 作为参数。

Java 利用Supplier创建日志消息 问题描述

用户希望创建由日志级别(log level)控制是否可见的日志消息。

Java 利用Supplier创建日志消息 解决方案

使用 java.util.logging.Logger 类新增的各种日志方法,它们传入 Supplier 作为参数。

Java 利用Supplier创建日志消息 具体实例

目前,Logger 类中的日志方法(如 infowarningsevere 等)包括两种重载形式,一种传入单个 String 作为参数,另一种传入 Supplier<String> 作为参数。
例 5-20 显示了各种日志方法的签名。7
7读者或许奇怪,Java 日志框架的设计者为什么不采用与其他日志 API 相同的日志级别(Trace、Debug、Info、Warn、Error、Fatal)。这是一个非常好的问题,如果读者找到答案,也请告诉作者。

例 5-20 Logger 类中各种日志方法的重载形式

void fine(String msg)
void fine(Supplier<String> msgSupplier)

void finer(String msg)
void finer(Supplier<String> msgSupplier)

void finest(String msg)
void finest(Supplier<String> msgSupplier)

void info(String msg)
void info(Supplier<String> msgSupplier)

void warning(String msg)
void warning(Supplier<String> msgSupplier)

void severe(String msg)
void severe(Supplier<String> msgSupplier)

每种方法的第一种重载形式(传入 String)是 Java 1.4 引入的,而第二种重载形式(传入 Supplier)是 Java 8 引入的,它在标准库中的实现如例 5-21 所示。

例 5-21 Logger 类的实现细节

public void info(Supplier<String> msgSupplier) {
    log(Level.INFO, msgSupplier);
}

public void log(Level level, Supplier<String> msgSupplier) {
    if (!isLoggable(level)) {                               ➊
        return;
    }
    LogRecord lr = new LogRecord(level, msgSupplier.get()); ➋
    doLog(lr);
}

❶ 如果不显示消息则返回
❷ 调用 get 方法以便在 Supplier 中检索消息
上述实现并非构建一个永远不会显示的消息,而是检查消息是否是“可记录的”(loggable)。如果所提供的消息是一个简单的字符串,程序将评估它是否已被记录。在上述日志方法中,第二种重载形式(传入 Supplier)支持在消息前添加空括号和箭头(() ->)以将其转换为 Supplier,且仅当日志级别合适时才会调用它。例 5-22 显示了 info 方法的两种重载形式。

例 5-22 在 info 方法中使用 Supplier

private Logger logger = Logger.getLogger(this.getClass().getName());
private List<String> data = new ArrayList<>();

// 用数据填充列表

logger.info("The data is " + data.toString());       ➊
logger.info(() -> "The data is " + data.toString()); ➋

❶ 无论是否显示 Info 消息,都会构建参数
❷ 仅当日志级别显示 Info 消息时,才会构建参数
可以看到,消息在列表的每个对象上调用 toString 方法。在第一条 logger.info 语句中,无论程序是否显示 Info 消息,都会创建结果字符串;在第二条 logger.info 语句中,在消息前添加 () -> 就能将日志参数转换为 Supplier,这意味着只有使用消息时才会调用 Supplierget 方法。
采用相同类型的 Supplier 替换参数的技术称为延迟执行(deferred execution),可以在任何对象创建成本较高的上下文中使用。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程