private static final Log logger = LogFactory.getLog(SpringProperties.class);java
对于使用PMD的任何人来讲,若是日志记录器没有声明为静态的和final的,那么这个博客的标题就会出如今PMD错误列表中。具体地说,LoggerIsNotStaticFinal规则简单地说日志应该声明为静态的和final的。我也喜欢确保他们是私人的。例如:日志
//雅加达公共日志记录对象
private static final Log log = LogFactory.getLog(MyClass.class);继承
上面的代码还显示了另外一个好的实践,即将Class对象传递给getLog()方法,而不是字符串。为何java.util...Logger类甚至不提供接受Class对象的方法呢?为何开发java.util.logging包的人将他们的API创建在Log4j上,却忽略了其中一些最有用的部分?哦,好吧。开发
如今说正题。为何声明日志记录器是私有的、静态的和final的良好实践呢?日志记录器是一个内部实现细节,所以它应该是私有的。对于类的全部实例,您只须要一个日志记录器,所以是静态的。而且记录器不能被替换,所以是最终的。因此若是这是好的,有什么很差的(至少在我看来)?Simple——任何不是私有的、静态的、final的记录器,而且不会将Class对象传递给getLog()!例如,考虑这个公共代码位,它在某个基类中声明:字符串
//记录器声明不太好get
protected final Log log = LogFactory.getLog(getClass());博客
为何这么糟糕?嗯,它不是静态的。另外一方面,它使用getClass()来获取日志。起初,这彷佛颇有效,由于如今全部子类都自动继承了正确运行时类型的现成的日志。这里出了什么问题?以这种方式声明的日志记录器的最大问题是,您如今从超类中得到的全部日志记录与子类的日志记录混合在一块儿,而且在日志输出中,除非您查看源代码,不然没法识别哪些消息来自哪一个类。若是超类有不少您不想看到的日志记录,这是很是烦人的,由于您不能过滤掉它。class
另外一个问题是,您以不一样的方式设置日志级别的能力消失了,例如,若是子类驻留在与超类不一样的包中。在这种状况下,若是试图从超类中筛选出日志记录,则不能,由于实际的运行时类用于获取日志记录器。扩展
最后,拥有一个受保护的记录器彷佛违反了基本的面向对象原则。为何子类应该从横切关注点的超类了解内部实现细节?不管如何,虽然这是一个愚蠢的小咆哮,可是当您扩展一个声明像这样的受保护日志记录器的超类时,它确实很烦人。