LoggerFactory.getLogger(ClassName.class)vs LoggerFactory.getLogger(this.getClass()。getName())

时间:2015-11-18 11:41:18

标签: java logging optimization reflection slf4j

我正在尝试提高Java的优化技能。为了实现这一目标,我制作了一个旧程序,并且我正在尽力使其变得更好。在这个程序中,我使用SL4J进行日志记录。为了得到记录器我做了:

private static final Logger logger = LoggerFactory.getLogger(this.getClass().getName());

在我编写代码的时候,我认为这是最好的选择,因为我删除了对类名的引用(可能会被重构)。但现在我不再那么肯定了......

private static final Logger logger = LoggerFactory.getLogger(ClassName.class);

另一方面,保留对类名的引用,但它会删除一个方法调用。对于一个班级来说,这可能不是一个很大的改进,但是当你有很多班级时,这可能就是一个问题。

所以我的问题是:

哪种方法更好?使用类名还是通过反射获取?

请用赞成和反对来激励你的答案。谢谢。

8 个答案:

答案 0 :(得分:10)

我会在这里分享我的观点。我会说这是你不应该从性能的角度来打扰的情况。可能在代码中有一些部分可以比这个更好地进行优化:)

现在,关于你的问题。查看LoggerFactory's代码

请注意,extract[Condition]只调用重载方法:

getLogger(Class<?> name)

并进行一些额外的计算。所以使用String的方法显然要快一些。

通常,模式是将Logger引用保持为类中的静态字段,如下所示:

Logger logger = getLogger(clazz.getName());

在这种情况下,您无法真正使用public class SomeClass { private static final Logger LOG = LoggerFactory.getLogger(SomeClass.class); } ,因为this.getClass()实际上并不存在(您在静态环境中运行)。

根据我的经验,最好使用this作为参数,除非您真的想要使用来自不同类的相同记录器。在这种情况下,您最好使用一些表示记录器的逻辑常量。

例如,我们假设您尝试使用3个不同的类来访问数据库。 因此,您创建了logger&#39; DB&#39;,分配一个将写入database.log的文件追加器,并且您希望在这3个不同的类中重用相同的记录器。

所以你应该使用以下代码:

ClassName.getClass()

希望这有帮助

答案 1 :(得分:6)

我通常做的是

private static final Logger logger = LoggerFactory.getLogger(ClassName.class);

然而,成语

protected final Logger log = LoggerFactory.getLogger(getClass());

同样很常见。 In this question您可以找到有关这些约定的更多信息。

答案 2 :(得分:5)

我更喜欢

/**
 * Expensive function
 * @param {string} lists
 * @returns {object}
 */
function expensiveFunction(lists){
    angular.forEach(lists, function (key, value) {
       lists.display = true; // here goes your logic
    });
    return lists;
}

var myList = expensiveFunction(myList);

<ul>
   <li ng-show="a.dispaly" ng-repeat="a in myList">
      <a ng-click="onMove(period)">Move here </a>
   </li>
   <li ng-hide="!canBook">
      <small>No free resources</small>
   </li>
</ul>

因为

Logger logger = LoggerFactory.getLogger(ClassName.class);

可以由其中一个类子项覆盖,您将在日志中看到子类名。有时它可能会令人困惑,因为日志实际上是在父类中执行的

答案 3 :(得分:3)

最新条目!

因为我将来可能会搜索这个。

有一种方法可以通过使用Java 7的MethodHandles类来创建对复制/粘贴友好的Logger实例(这几乎绝对不是做某事的好理由!)。

private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

答案 4 :(得分:0)

如果您在每次声明记录器时都不想编写类名,可以使用以下实用程序方法:

    public static org.slf4j.Logger getLogger() {
        final Throwable t = new Throwable();
        t.fillInStackTrace();
        return LoggerFactory.getLogger(t.getStackTrace()[1].getClassName());
    }

该方法可以使用:

private static final Logger LOG = TheClassContainingTheMethod.getLogger();

使用这种方法,记录器声明对于所有类始终是相同的。

答案 5 :(得分:0)

在静态环境中,您不能使用LoggerFactory.getLogger(getClass())LoggerFactory.getLogger(this.getClass().getName())

然后您必须使用LoggerFactory.getLogger(ClassName.class)

无论如何,我更喜欢Lombok的@Log4j2,更少的代码就能完成工作:https://projectlombok.org/api/lombok/extern/log4j/Log4j2.html

答案 6 :(得分:-2)

我用这个

private static final Logger log = LoggerFactory.getLogger(ClassName.class);

答案 7 :(得分:-2)

使用此

private final Logger logger = LoggerFactory.getLogger(this.getClass()); 

}
// logic
try
{
// todo
}

catch (NullPointerException e) {
        logger.error("Error:-" + e.getMessage());
          return ResponseUtil.errorResponse(e.getMessage());
        }

        catch (Exception e) {
            logger.error("Error:-" + e.getMessage());
            return ResponseUtil.errorResponse(e.getMessage());
        }