Log4j2 惰性 lambda 评估:Groovy 有机会吗?

Log4j2 lazy lambda evaluation: Any chance in Groovy?

问题似乎是 Log4j2 的纯 Java 实现不提供 Closure 参数(或 lambda 参数,如果有的话),而是在方法签名中提供一个简单的 Object 参数。 Groovy (3.0.8) 将 Java 风格的 lambda 和方法引用转换为闭包,而 Log4j 似乎只是在它们上调用 .toString() 。因此,下面代码的日志输出看起来像这样,这显然不是预期的结果,来自 Java:

13:55:39.417 [main] INFO  Messenger - test$_runCode_closure1@f391e52
13:55:39.417 [main] INFO  Messenger - test$_runCode_closure2@4b518645
13:55:39.417 [main] INFO  Messenger - org.codehaus.groovy.runtime.MethodClosure@294a3f2a
import org.apache.logging.log4j.LogManager

def log2 = LogManager.getLogger("Messenger")

log2.info("{}", () -> "Expensive message")
log2.info ("{}") { "Expensive message" }
log2.info("{}", this::someString)

static String someString() {
    return "Expensive message"
}

在 Groovy 中有什么方法可以用 Java lambda 而不是 Groovy 闭包结束吗? Groovy 为 Logger 方法提供带有闭包的方法签名的扩展可以作为答案吗?

免责声明:不是正确答案,而是解决方法。

Groovys GString 也可以使用闭包,每次调用 GString 必须显示为 String。

例如

def a = 42
def gs = "${a} ${-> a}"
println gs
// → 42 42
a = 666
println gs
// → 42 666

所以你可以使用:

log2.info ("${ -> "Expensive message" }")

郑重声明:所有这些都给了我 Object 而不是 Supplier 摆弄的版本:

log2.info('{}', {42} as Supplier)
log2.info('{}', [{42}].toArray())
log2.info('{}', [{42}] as Supplier[])
log2.info('{}', [{42}] as Supplier<Long>[])
log2.info('{}', new Supplier() { Object get() { 42 } })
log2.info('{}', *[{42}])

都不能与 @CompileStatic 一起使用(最后一个除外,它根本无法编译)。使用 Groovy 4.0.0-alpha3

测试

有一个仅将供应商作为参数的变体:

log2.info({ "Expensive message" } as Supplier)