非静态日志可以证明合理吗?

时间:2011-01-27 14:22:42

标签: java static logging

我是代码库中唯一使用Apache commons日志记录完成日志记录的维护者。

所有类都包含这两个导入:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

然后很多类都包含非静态日志实例化,如下所示:

/** The log. */
private Log log = LogFactory.getLog(Xyz.class);

这可以证明这是合理的吗?

我可以安全地将所有这些更改为静态调用吗?

编辑关于它(显然)方便的特殊情况:我的问题实际上是“整个代码库中的非静态日志是否合理?” < / p>

4 个答案:

答案 0 :(得分:8)

这取决于。这来自documentation

  

请注意,对于应用程序代码,将日志成员声明为“static”更有效,因为每个类创建一个Log对象,建议使用。但是,对于可以通过servlet或j2ee容器或类似环境中的“共享”类加载器部署的类来说,这是不安全的。如果最终使用不同的thread-context-classloader值设置调用该类,则不能将该成员声明为static。因此,在任何“库”类型项目的代码中应避免使用“静态”。

答案 1 :(得分:5)

您必须非常小心地将非静态记录器初始化为您的代码段在Serializable类中执行的方式。

首先,因为Log不可序列化,所以任何序列化类的尝试都会失败。如果你声明你的记录器transient,那么合乎逻辑的做法是,反序列化后你的log字段不会被初始化,所以你在尝试记录东西时会得到一个NPE 。不太好的情况。

总而言之,如果您愿意,可以使用非静态记录器,但在使用它们之前请确保它们已初始化。但除此之外,我不会担心非静态记录器,大多数日志记录实现总是会返回相同的记录器对象(log4j肯定会)。

答案 2 :(得分:2)

一个实例是一个非静态记录器,是一种基本类,它为子类提供了一个日志实例(为方便起见)。请考虑以下示例:

public abstract class Pet
{
   protected Log log;

   public Pet()
   {
      log = LogFactory.getLog(this.getClass());
   }

   public void wash()
   {
      log.info("Get the hose.");
   }
   ...
}

public class Cat extends Pet
{
   ...
   public void doSomethingUseful()
   {
      log.warn("I can't, I am a cat.");
   }
}

在此示例中,日志记录将来自“Cat”日志实例。这是不使用静态记录器的有效理由吗?也许不适用于从Cat类记录的消息,但从Cat日志实例下的Pet类记录的消息可能会有所帮助。

答案 3 :(得分:0)

这是一篇暗示相反的文章。实际上,在复杂情况下,库中的静态记录器可能会出现类加载问题。所以,可以证明非静态记录器是合理的。

  

但是考虑使用“private static Log log =”的类的情况   ...“通过多个祖先的ClassLoader部署   据说是独立的“应用程序”。在这种情况下,日志成员是   只初始化一次,因为只有一个类的副本。   初始化(通常)在任何代码第一次尝试时发生   实例化该类或在其上调用静态方法。什么时候   发生类的初始化,应该设置日志成员   到?

http://wiki.apache.org/commons/Logging/StaticLog