我在库中有一个基类,它有大量的调试级日志语句。该库用于不同的应用程序,基类是子类。我希望能够根据使用它的特定派生类来配置基类的日志记录级别。什么是实现这个目标的有用成语?
例如,以下是起点:
class Base {
static Logger logger = Logger.getLogger(Base.class);
protected final void foo() {
logger.debug("foo");
}
}
class DerivedA extends Base {
public void boo() {
foo();
}
}
class DerivedB extends Base {
public void boo() {
foo();
}
}
鉴于上述情况,我无法启用DerivedA
的日志记录,但无法启用DerivedB
的日志记录。
相反,我必须做以下事情:
abstract class Base {
abstract protected Class getDerivedType();
protected final void foo() {
Logger logger = Logger.getLogger(getDerivedType());
logger.debug("foo");
}
}
class DerivedA extends Base {
public void boo() {
foo();
}
@Override protected Class getDerivedType() {
return DerivedA.class;
}
}
class DerivedB extends Base {
public void boo() {
foo();
}
@Override protected Class getDerivedType() {
return DerivedB.class;
}
}
...鉴于上述情况,我可以在log4j.properties
文件中使用不同的日志级别,具体取决于派生类:
log4j.logger.a.DerivedA=debug
log4j.logger.a.DerivedB=info
虽然上面的 工作,但我不喜欢我的logger
对象不再是静态的事实,必须在每个方法中重新定义。另外,我必须为派生类定义一个抽象方法以提供它们的具体类型,而不是为了能够自定义日志记录而感觉不自然。
以上是惯用的,如果没有,会有什么更好的方法来达到同样的效果?
通常,有没有办法根据上下文配置日志记录? (在这种情况下,上下文是派生类,但也可以是调用堆栈,即调用发生日志记录的特定方法的方法)。或者这种级别的日志记录可配置性是否真的不受支持,甚至是一个坏主意?
答案 0 :(得分:3)
使用非静态记录器的一种可能解决方案:
public class Base {
protected Logger logger = Logger.getLogger(Base.class);
protected final void foo() {
logger.debug("foo");
}
}
class DerivedA extends Base {
{
logger = Logger.getLogger(DerivedA.class);
}
public void boo() { foo(); }
}
class DerivedB extends Base {
{
logger = Logger.getLogger(DerivedB.class);
}
public void boo() { foo(); }
}
即使logger
不是静态的,这个结构也不像原始结构那么复杂。
替代解决方案:子类必须实现getLogger()
抽象方法(它们可以简单地返回静态记录器),该方法在基类中用于记录。记录器可以是静态的。
public abstract class Base {
protected abstract Logger getLogger();
protected final void foo() {
getLogger().debug("foo");
}
}
class DerivedA extends Base {
private static final Logger logger = Logger.getLogger(DerivedA.class);
public void boo() { foo(); }
protected Logger getLogger() { return logger; }
}
class DerivedB extends Base {
private static Logger logger = Logger.getLogger(DerivedB.class);
public void boo() { foo();}
protected Logger getLogger() { return logger; }
}
这两种方法都适用于您当前的属性文件。