Should logger be private static or not

Should logger be declared static or not? Usually I've seen two types of declaration for a logger :

protected Log log = new Log4JLogger(aClass.class);

or

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

Which one should be used? what are the pro's and con's of both?

48599 次浏览

The advantage of the non-static form is that you can declare it in an (abstract) base class like follows without worrying that the right classname will be used:

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

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

On the other hand, if you obtain the logger by a factory which in turn may cache the already-instantiated loggers, then using the non-static form won't add that much overhead. Log4j for example has a LogManager for this purpose.

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

使用控制反转并将日志记录器传递给构造函数。如果您在类中创建日志记录器,那么您的单元测试将会非常困难。您正在编写单元测试,不是吗?

最重要的区别是它如何影响您的日志文件: 日志应该放在哪个类别中?

  • 在您的第一个选择中,子类的日志最终会出现在超类的类别中。这对我来说似乎非常违反直觉。
  • 你的第一个案例有一个变体:

    Protected Loglog = new Log4JLogger (getClass ()) ;

    在这种情况下,您的日志类别说明记录的代码正在处理的对象。

  • 在第二个选择(私有静态)中,日志类别是包含日志代码的类。通常情况下,执行被记录的操作的类。

I would strongly recommend that last option. It has these advantages, compared to the other solutions:

  • 日志和代码之间有直接的关系。很容易找到日志消息的来源。
  • 如果有人必须调优日志记录级别(每个类别都要调优) ,通常是因为他们对某个特定类编写的某些特定消息感兴趣(或者不感兴趣)。如果类别不是编写消息的类,则更难调优级别。
  • You can log in static methods
  • 每个类只需要初始化(或查找)一次日志记录器,因此在启动时,而不是对每个创建的实例。

它也有缺点:

  • 它需要在记录消息的每个类中声明(不能重用超类日志记录器)。
  • 在初始化日志记录器时,需要注意放置正确的类名。(但是好的 IDE 会帮你解决这个问题)。

我曾经认为所有的日志记录器都应该是静态的; 然而,this article at wiki.apache.org提出了一些关于类加载器泄漏的重要内存问题。将日志记录器声明为静态的,可以防止在使用共享类加载器的 J2EE 容器中对声明类(和相关的类加载器)进行垃圾收集。如果重新部署应用程序的次数足够多,这将导致 PermGen 错误。

除了将日志记录器声明为非静态外,我实在看不出有什么办法可以解决这个类加载器泄漏问题。