我是代码库中唯一使用Apache commons日志记录完成日志记录的维护者。
所有类都包含这两个导入:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
然后很多类都包含非静态日志实例化,如下所示:
/** The log. */
private Log log = LogFactory.getLog(Xyz.class);
这可以证明这是合理的吗?
我可以安全地将所有这些更改为静态调用吗?
编辑关于它(显然)方便的特殊情况:我的问题实际上是“整个代码库中的非静态日志是否合理?” < / p>
答案 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部署 据说是独立的“应用程序”。在这种情况下,日志成员是 只初始化一次,因为只有一个类的副本。 初始化(通常)在任何代码第一次尝试时发生 实例化该类或在其上调用静态方法。什么时候 发生类的初始化,应该设置日志成员 到?