在使用logger.debug()之前是否需要Log4j isDebugEnabled()?

当我浏览一些代码时,我注意到使用logger如下,

if(logger.isDebugEnabled()) logger.debug("Something.."); 

但在某些代码中,我观察到了这样的情况。

 logger.debug("Something.."); 

当我查看log4j的源代码时,在Logger本身的debug()方法中检查了if(logger.isDebugEnabled()) 。 那么为什么我们需要这个不必要的开销if(logger.isDebugEnabled()) ??

传递给logger.debug(...)的String需要时间来评估时很有用,在这种情况下,如果未启用调试,则可以跳过此评估。

 if(logger.isDebugEnabled()) { logger.debug("The meaning of life is " + calculateMeaningOfLife()); } 

IMO这使得代码的可读性低得多,因此只有在性能显着提高时才能使用。

isDebugEnabled通常用于避免不必要的字符串连接,例如此调用

 logger.debug("Line number = " + n); 

首先调用Strings concatination然后调试debug()然后只有Logger检测到调试没有启用并且只是返回。 这可能会显着影响应用性能。

在SLF4J中解决了这个问题,SLF4J已经格式化了这样的日志记录方法

 public void debug(String format, Object arg); 

Java必须首先解析传递给调试方法的字符串参数,然后才能调用它。

 logger.debug("Something.. var1=" + variable1 + " var2=" + variable2); 

上面的代码将导致创建多个String对象,因为每个+创建另一个String,因此在调用方法之前,您将创建大约5个或更多对象。

调试通常不会启用,因此检查启用调试是否比始终解析参数更有效。

该声明:

 if(log.isDebugEnabled()){ 

仅用于性能原因。 它的使用是可选的,因为它在内部由log方法调用。

但是现在你问这个检查是否是内部检查的,那我为什么要使用呢? 这很简单:如果你记录这么简单:

 log.debug("ResultSet rs is retrieved from OracleTypes"); 

然后你不需要做任何检查。 如果你使用append运算符(+)组成一个字符串来记录,如下所示:

 log.debug("[" + System.getTimeInMillis() + "] ResultSet rs is retrieved from OracleTypes"); 

在这种情况下,您应该检查日志是否已启用,因为如果不是,即使没有创建日志,字符串组成也是如此。 我必须提醒你,使用运算符“+”来连接字符串是非常低效的。

SLF4J实现(在1.7.10版本上检查isDebugEnabled()在某些方法中调用isDebugEnabled() ,例如:

 public void debug(String format, Object... arguments) { if(this.log.isDebugEnabled()) { FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); this.log.debug(ft.getMessage(), ft.getThrowable()); } } 

但也有方法重载,它不会在内部检查是否启用了给定的登录级别,如:

 public void debug(String msg, Throwable t) { this.log.debug(msg, t); } 

另一件事是可以更改Logger实现,因此如果您想要始终确保根据日志记录级别调用记录器,那么您可能需要考虑使用isDebugEnabled()方法。