Log4j 2.x 如何实现惰性参数求值?

How does Log4j 2.x implement lazy argument evaluation?

给定 Java argument evaluation mechanism, how does Log4j 2.x implement lazy evaluation 当使用大括号格式化消息时 "to avoid the cost of parameter construction" 当日志被禁用时?

例如

logger.debug("Entry number: {} is {}", i, entry[i]);

我猜 Log4j 的意思是,使用大括号,他们避免在不需要时构造字符串(例如,Level 不是 Debug):

logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));

始终计算完整的消息,即使它不会被记录。

logger.debug("Entry number: {} is {}", i, entry[i]);

Log4j可以先检查Log-Level,再决定是否值得构造消息字符串。这节省了字符串连接所需的资源。它只会在实际创建消息时对提供的对象调用 toString(),从而节省进一步的计算成本。

Log4j 使用内部 class (org.apache.logging.log4j.message.ParameterFormatter) 将每个 {} 替换为提供的参数。它还将捕获 toString() 抛出的异常并报告这些失败。

为避免参数求值,只需将其包装在 lambda 中即可:

logger.debug(() -> { 
   "Entry number: " + i + " is " + String.valueOf(entry[i])
});

在这种形式下,只有在实际采伐之前才会调用供应商进行施工。把它想象成一个函数声明。