2017-03-09 183 views
2

我有一個庫中的基類,有大量的調試級別日誌語句。這個庫用於不同的應用程序,基類是子類。我希望能夠根據使用它的特定派生類來配置基類的日誌記錄級別。實現這個有用的習慣用法是什麼?如何在基類中配置日誌,基於Log4J中的派生類?

例如,下面的出發點:

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對象不能是靜態的在每種方法中都需要重新定義。此外,我感到不自然的是,我必須爲派生類定義一個抽象方法,以提供它們的具體類型,除了能夠自定義日誌記錄之外別無其他原因。

以上是否是慣用的,如果不是,將會是更好的方式來達到相同的效果?

一般來說,有沒有辦法根據上下文配置日誌記錄? (在這種情況下,上下文是派生類,但也可以是調用堆棧,即調用發生日誌記錄的特定方法的方法)。還是這種級別的日誌可配置性沒有得到真正的支持,甚至是一個壞主意?非靜態記錄器

回答

2

一種可能的解決方案:

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; } 
} 

這兩種方法都適用於您當前的屬性文件。