使用抽象类的 Java 日志记录

我正在做一个项目,目前正在用 log4j 实现一些日志,我很好奇我应该如何实现这些日志。我正在推行的两项措施如下:

第一个选项

对超类和所有子类使用单个日志:

public abstract class AbstractFoo {
protected static Log LOG = LogFactory.getLog(AbstractFoo.class);


...
}


public class Foo extends AbstractFoo {
public void someMethod() {
LOG.info("Using abstract log");
}
}

第二个选项

对每个类、 super 和 subs 使用单独的日志:

public abstract class AbstractFoo {
private static Log LOG = LogFactory.getLog(AbstractFoo.class);


...
}


public class Foo extends AbstractFoo {
private static Log LOG = LogFactory.getLog(Foo.class);


public void someMethod() {
LOG.info("Using own log");
}
}

什么更合理,为什么?

45648 次浏览

我不会这样做,相反,我会让它在两种情况下都使用正确的类。

public abstract class AbstractFoo {
protected final Log log = LogFactory.getLog(getClass());


...
}


public class Foo extends AbstractFoo {
public void someMethod() {
log.info("Using abstract log");
}
}

如果您没有进行大量的日志记录(无论如何这是一个好主意) ,您可以使用一个方法来代替。

public abstract class AbstractFoo {
protected Log log() { return LogFactory.getLog(getClass()); }


...
}

如果有一个类经常调用它,那么您可以重写它,从而得到一个缓存的实例。

两者都有意义,这取决于您的应用程序。

我认为更常用的做法是为每个类安装私有日志记录器。这允许您配置每个类和每个包的日志记录。请记住,AbstractFooFoo可能属于不同的包,您可能只想查看来自 Foo的日志。

另外,如果你想写 protected字段,一定要三思而后行。这不是完全禁止的,而是众所周知的坏习惯。它使您的代码不易阅读,并且难以维护。

如果您在抽象类中创建日志记录器,那么所有的日志都将被标记为源自 AbstractFoo。如果您希望/需要看到用发生日志的子类标记的日志,请为子类创建日志记录器。

这是我的解决方案(最终静态日志记录器) :

public abstract class AbstractFoo {
protected abstract Log getLogger();
public doSomething() {
getLogger().info("log something");
}
}


public class Foo extends AbstractFoo {
private static final Log log = Log.getLogger(Foo.class);


protected Log getLogger() {
return log;
}
public doSomethingElse() {
log.info("log somethingElse");
}
}

通过使用构造函数也可以实现同样的目的。在 基地类级别添加日志记录器,并使用 super ()从每个 导出类设置它。这就是密码:

public abstract class AbstractFoo {


protected Log log;  // base abstract class has a Log object.


public AbstractFoo(Log logger) {   // parameterized constructor for logger, to be used by the derived class.
this.log = logger;
}


public doSomething() {        // common method for all the derived classes.
log.info("log something");
}
// rest of business logic.
}


public class Foo extends AbstractFoo {


public Foo(){
super(LogFactory.getLog(AbstractFoo.class));
}


public void someMethod() {
log.info("Using own log");     // this uses its own logger.
}
}