记录器是否应声明为静态?通常我会看到两种类型的记录器声明:
protected Log log = new Log4JLogger(aClass.class);
或
private static Log log = new Log4JLogger(aClass.class);
应该使用哪一个?这两者的专业和概念是什么?
答案 0 :(得分:92)
非静态表单的优点是您可以在(抽象)基类中声明它,如下所示,而不必担心将使用正确的类名:
protected Log log = new Log4JLogger(getClass());
然而,它的缺点显然是将为该类的每个实例创建一个全新的记录器实例。这可能本身并不昂贵,但它增加了很大的开销。如果您想避免这种情况,则需要使用static
表单。但它的缺点反过来是你必须在每个单独的类中声明它并注意在记录器构造期间使用了正确的类名的每个类,因为getClass()
不能在静态上下文中使用。但是,在普通的IDE中,您可以为此创建自动完成模板。例如。 logger
+ ctrl+space
。
另一方面,如果您通过工厂获取记录器,而工厂又可以缓存已经实例化的记录器,那么使用非静态表单不会增加太多开销。例如,Log4j为此目的有一个LogManager
。
protected Log log = LogManager.getLogger(getClass());
答案 1 :(得分:43)
我曾经认为所有记录器都应该是静态的;但是,this article at wiki.apache.org提出了一些关于类加载器泄漏的重要内存问题。将logger声明为static会阻止声明类(和关联的类加载器)在使用共享类加载器的J2EE容器中进行垃圾回收。如果您重新部署应用程序足够多次,这将导致PermGen错误。
除了将记录器声明为非静态外,我真的没有办法解决这个类加载器泄漏问题。
答案 2 :(得分:15)
最重要的区别在于它如何影响您的日志文件:日志在哪个类别中?
您的第一个案例有一个变体:
protected Log log = new Log4JLogger(getClass());
在这种情况下,您的日志类别会说明记录的代码正在处理哪个对象。
在您的第二个选择(私有静态)中,日志类别是包含日志记录代码的类。通常是正在记录事物的类。
我强烈建议最后一个选项。与其他解决方案相比,它具有以下优势:
它也有缺点:
答案 3 :(得分:3)
使用控制反转并将记录器传递给构造函数。如果你在课堂上创建了记录器,那么你的单元测试将会有一段时间。你在写单元测试不是吗?