Java 记录器是否应该是私有静态的

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3842823/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 05:43:31  来源:igfitidea点击:

Should logger be private static or not

javalogging

提问by Drahakar

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

记录器是否应该声明为静态?通常我见过两种类型的 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?

应该使用哪一种?两者的优点和缺点是什么?

采纳答案by BalusC

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());

However its disadvantage is obviously that a whole new logger instance will be created for every instance of the class. This may not per se be expensive, but it adds a significant overhead. If you'd like to avoid this, you'd like to use the staticform instead. But its disadvantage is in turn that you have to declare it in every individual class and take care in every class that the right classname is been used during logger's construction because getClass()cannot be used in static context. However, in the average IDE you can create an autocomplete template for this. E.g. logger+ ctrl+space.

然而,它的缺点显然是将为类的每个实例创建一个全新的记录器实例。这本身可能并不昂贵,但会增加大量开销。如果您想避免这种情况,您可以改用static表格。但它的缺点是你必须在每个单独的类中声明它,并在每个类中注意在记录器的构造过程中使用正确的类名,因为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 LogManagerfor this purpose.

另一方面,如果您通过工厂获取记录器,而该工厂又可以缓存已经实例化的记录器,那么使用非静态形式不会增加太多开销。例如,Log4j 有一个LogManager用于此目的。

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

回答by Wayne Allen

Use inversion of control and pass the logger into the constructor. If you create the logger inside the class you are going to have a devil of a time with your unit tests. You are writing unit tests aren't you?

使用控制反转并将记录器传递给构造函数。如果您在类中创建记录器,您的单元测试将会有一段时间。您正在编写单元测试,不是吗?

回答by Wouter Coekaerts

The most important difference is how it affects your log files: in which category do logs go?

最重要的区别在于它如何影响您的日志文件:日志属于哪个类别?

  • In your first choice, the logs of a subclass end up in the category of the superclass. That seem very counter-intuitive to me.
  • There is a variant of your first case:

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

    In that case, your log category says which object the code that logged was working on.

  • In your second choice (private static), the log category is the class that contains the logging code. So normally the class that is doing the thing that is being logged.

  • 在您的第一个选择中,子类的日志最终归入超类的类别中。这对我来说似乎非常违反直觉。
  • 您的第一种情况有一个变体:

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

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

  • 在您的第二个选择(私有静态)中,日志类别是包含日志代码的类。所以通常是正在做正在记录的事情的班级。

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

我强烈推荐最后一个选项。与其他解决方案相比,它具有以下优势:

  • There is a direct relation between the log and the code. It is easy to find back where a log message came from.
  • If someone has to tune logging levels (which is done per category), it is usually because they are interested (or not) in some particular messages, written by a particular class. If the category is not the class that is writing the messages, it is harder to tune the levels.
  • You can log in static methods
  • Loggers only need to be initialized (or looked up) once per class, so at startup, instead of for every instance created.
  • 日志和代码之间有直接关系。很容易找到日志消息的来源。
  • 如果有人必须调整日志记录级别(按类别完成),通常是因为他们对由特定类编写的某些特定消息感兴趣(或不感兴趣)。如果类别不是编写消息的类,则很难调整级别。
  • 您可以登录静态方法
  • 记录器每个类只需要初始化(或查找)一次,所以在启动时,而不是为每个创建的实例。

It also has disadvantages:

它也有缺点:

  • It needs to be declared in every class where you log messages (no reuse of superclass loggers).
  • You need to take care to put the right classname when initializing the logger. (But good IDE's take care of that for you).
  • 它需要在您记录消息的每个类中声明(不重用超类记录器)。
  • 初始化记录器时,您需要注意放置正确的类名。(但是好的 IDE 会为您处理这些)。

回答by piepera

I used to think that all loggers should be static; however, this article at wiki.apache.orgbrings up some important memory concerns, regarding classloader leaks. Declaring a logger as static prevents the declaring class (and associated classloaders) from being garbage collected in J2EE containers that use a shared classloader. This will result in PermGen errors if you redeploy your application enough times.

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

I don't really see any way to work around this classloader leak issue, other than declaring loggers as non-static.

除了将记录器声明为非静态之外,我真的没有看到任何方法可以解决这个类加载器泄漏问题。