2011-01-27 66 views
8

我是使用Apache公共日志记录完成日志记录的代码库上的唯一维护者。非静态日志可以证明吗?

所有课程包含这两个进口:

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

然后大量类包含这样的非静态日志实例:

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

可以这样是否合理?

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

编辑关于特殊情况下,它可以(显然)是很方便:“能非静态日志遍布代码库是合理的”我的问题真的是越来越

回答

5

对于让非静态记录器初始化您的代码片段在Serializable类中执行的方式,您必须格外小心。

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

因此,总结一下,如果您愿意,可以使用非静态记录器,但要确保在使用它们之前对它们进行了初始化。但除此之外,我不会担心非静态记录器,大多数记录器实现总是会返回相同的记录器对象(log4j肯定会这样做)。

8

这取决于。这是从documentation

注意,对于应用程序代码,宣告日志构件为“静态”是更有效的作为一个登录的对象为每个类创建,并且被推荐的。然而,这对于可能通过servlet或j2ee容器或类似环境中的“共享”类加载器部署的类来说并不安全。如果该类可能最终以不同的线程上下文类加载器值进行调用,则该成员不能声明为静态。因此,在任何“库”类型的项目中都应该避免使用“静态”代码。

+0

已经阅读文档,这是我不明白什么是错的声明登录场即使是在共享类加载器环境为静态的。除此之外,可以将LogFactory.getLog()类参数更改为String(Xyz.class.getName()),除此之外,从具有不同线程上下文类加载器的类访问记录器的危害在哪里?无论如何,日志方法应该是线程安全的,如果不是,你会遇到更大的问题。 任何人都可以提供一个明确的描述什么可以出错与静态日志引用? – 2011-01-27 14:51:07

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类记录的消息可能会有所帮助。

0

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

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

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