我需要类似于String.format(...)方法的东西,但是有懒惰的评估.
这个lazyFormat方法应该返回一些对象,其toString()方法将评估格式模式.
我怀疑有人已经这样做了.这可以在任何图书馆中找到吗?
我想替换它(logger是log4j实例):
if(logger.isDebugEnabled() ) { logger.debug(String.format("some texts %s with patterns %s", object1, object2)); }
有了这个:
logger.debug(lazyFormat("some texts %s with patterns %s", object1, object2));
只有在启用调试日志记录时,我才需要lazyFormat来格式化字符串.
如果您正在寻找一个"简单"的解决方案:
public class LazyFormat { public static void main(String[] args) { Object o = lazyFormat("some texts %s with patterns %s", "looong string", "another loooong string"); System.out.println(o); } private static Object lazyFormat(final String s, final Object... o) { return new Object() { @Override public String toString() { return String.format(s,o); } }; } }
输出:
一些文字looong字符串与图案另一个loooong字符串
你当然可以isDebugEnabled()
在lazyFormat中添加任何语句.
它可以通过在最新的log4j 2.X版本http://logging.apache.org/log4j/2.x/log4j-users-guide.pdf中使用参数替换来完成:
4.1.1.2参数替换
日志记录的目的通常是提供有关系统中发生的事情的信息,这需要包含有关被操纵对象的信息.在Log4j 1.x中,这可以通过以下方式完成:
if (logger.isDebugEnabled()) { logger.debug("Logging in user " + user.getName() + " with id " + user.getId()); }
反复执行此操作会使代码感觉更像是关于日志记录而不是手头的实际任务.此外,它会导致两次检查日志记录级别; 一次调用isDebugEnabled,一次调试方法.一个更好的选择是:
logger.debug("Logging in user {} with id {}", user.getName(), user.getId());
使用上面的代码,只会检查一次日志记录级别,并且只有在启用调试日志记录时才会发生字符串构造.
如果你为了高效的日志记录寻找懒惰的连接,看看Slf4J 这可以让你写:
LOGGER.debug("this is my long string {}", fatObject);
字符串连接仅在设置了调试级别时才会发生.
重要说明:强烈建议移动所有日志记录代码以使用SLF4J(尤其是log4j 1.x).它可以保护您免受任何特定日志记录实现的特殊问题(即错误)的困扰.它不仅具有已知的后端实现问题的"修复",而且还适用于多年来出现的更快的更快实现.
在直接回答您的问题时,这里使用SLF4J会是什么样子:
LOGGER.debug("some texts {} with patterns {}", object1, object2);
您提供的最重要的一点是您传递两个Object实例.该object1.toString()
和object2.toString()
方法不立即进行评估.更重要的toString()
是,只有在实际使用它们返回的数据时,才会评估这些方法; 即懒惰评价的真正含义.
我试着想到一个更普遍的模式,我可以使用它不需要我必须覆盖toString()
大量的类(并且有些类我无权访问覆盖).我提出了一个简单的即插即用解决方案.再次,使用SLF4J,我只在/当启用了级别的日志记录时才编写字符串.这是我的代码:
class SimpleSfl4jLazyStringEvaluation { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleSfl4jLazyStringEvaluation.class); ... public void someCodeSomewhereInTheClass() { //all the code between here LOGGER.debug( "{}" , new Object() { @Override public String toString() { return "someExpensiveInternalState=" + getSomeExpensiveInternalState(); } } //and here can be turned into a one liner ); } private String getSomeExpensiveInternalState() { //do expensive string generation/concatenation here } }
并且要简化为单行,您可以缩短someCodeSomewhereInTheClass()中的LOGGER行:
LOGGER.debug("{}", new Object(){@Override public String toString(){return "someExpensiveInternalState=" + getSomeExpensiveInternalState();}});
我现在已经重构了我的所有日志代码以遵循这个简单的模型.它已经大大整理了一切.现在当我看到任何不使用它的日志代码时,我重构日志代码以使用这个新模式,即使它还需要.这样,如果/稍后进行更改需要添加一些"昂贵"操作,则基础结构样板已经在那里简化了添加操作的任务.