logging器应该是私有的静态或不

logging器是否应声明为静态? 通常我已经看到了两种types的logging器声明:

    保护日志日志=新Log4JLogger(aClass.class);

要么

     private static Log log = new Log4JLogger(aClass.class);

哪一个应该使用? 什么是两者的亲和骗局?

非静态表单的好处是你可以像下面那样在(抽象)基类中声明它,而不用担心会使用正确的类名:

 protected Log log = new Log4JLogger(getClass()); 

然而,它的缺点显然是将为每个类的实例创build一个全新的logging器实例。 这本身可能并不昂贵,但是会增加很大的开销。 如果你想避免这种情况,你想使用staticforms。 但是它的缺点是你必须在每个单独的类中声明它,并在每个类中注意在logging器的构造过程中使用了正确的类名,因为getClass()不能在静态上下文中使用。 但是,在平均IDE中,您可以为此创build一个自动完成模板。 例如logger + ctrl+space

另一方面,如果您通过工厂获取logging器,而工厂又可以caching已经实例化的logging器,那么使用非静态表单将不会增加那么多的开销。 例如Log4j有一个LogManager用于这个目的。

 protected Log log = LogManager.getLogger(getClass()); 

我曾经认为,所有伐木者应该是静态的; 然而, 这篇文章在wiki.apache.org上提到了一些关于类加载器泄漏的重要的内存问题。 将logging器声明为静态可防止声明类(和关联的类加载器)在使用共享类加载器的J2EE容器中被垃圾收集。 这会导致PermGen错误,如果您重新部署您的应用程序足够多的时间。

我真的没有办法解决这个类加载器泄漏问题,除了声明logging器是非静态的。

最重要的区别是它如何影响你的日志文件:日志去哪个类别?

  • 在你的第一个select中,子类的日志以超类的类别结束。 这对我来说似乎是非常直观的。
  • 你的第一个案例有一个变种:

    保护日志日志=新Log4JLogger(getClass());

    在这种情况下,您的日志类别将logging正在处理的代码的哪个对象。

  • 在第二种select(私有静态)中,日志类别是包含日志代码的类。 所以正常情况下,正在做logging的东西的类。

我强烈build议最后的select。 与其他解决scheme相比,它具有以下优点:

  • 日志和代码之间有直接的关系。 很容易find日志消息来自哪里。
  • 如果有人需要调整日志级别(这是每个类别完成的),通常是因为他们对特定的消息感兴趣(或不是),特定的消息由特定的类编写。 如果类别不是正在编写消息的类,则难以调整级别。
  • 您可以login静态方法
  • logging器只需要每个类初始化(或查找)一次,所以在启动时,而不是每个创build的实例。

它也有缺点:

  • 它需要在你logging消息的每个类中声明(不要重用超类logging器)。
  • 在初始化logging器时,需要注意input正确的类名。 (但好的IDE为你照顾)。

使用控制反转并将logging器传递给构造函数。 如果你在课堂上创buildlogging器,那么你的unit testing将会有一段时间。 你正在写unit testing不是吗?