2010-06-14 78 views
3

我有一些代碼是由30多個類組成的獨立Java應用程序。在獨立的java應用程序中使用相同的log4j記錄器

大多數這些繼承自一些其他基類。

每類都有這個方法來獲取和使用log4j的記錄

public static Logger getLogger() { 
    if (logger != null) return logger; 
    try { 
     PropertyUtil propUtil = PropertyUtil.getInstance("app-log.properties"); 
     if (propUtil != null && propUtil.getProperties() != null) 
      PropertyConfigurator.configure(propUtil.getProperties()); 
     logger = Logger.getLogger(ExtractData.class); 
     return logger; 
    } catch (Exception exception) { 
     exception.printStackTrace(); 
    } 
} 

A)我的問題是,這是否應該重構爲一個被所有類初始化一次和整個中常用的一些記錄?這是一個更好的做法嗎?

B)如果是,那怎麼辦?我怎樣才能通過記錄器?

C)實際上在代碼中使用的不是Logger.debug()而是getLogger().debug()。 這對性能有什麼影響?

+0

我可能是錯的,但我不認爲PropertyConfigurer.configure()是線程安全的 - 所以如果你的代碼是多線程的,從多線程調用這個getLogger()方法可能會導致問題。最好使用PéterTörök – 2010-06-14 15:29:01

+0

@matt b概述的標準log4j用法 - 謝謝指出。我將檢查使用情況,因爲此代碼可能是從多個線程執行的。 – shinynewbike 2010-06-14 16:41:29

回答

8

A)在Log4J中,您有記錄器層次結構,而不是單個記錄器。這通常歸結爲每個類的一個記錄器,其中記錄器由類名標識。該記錄儀初始化這樣的:

private static final Logger logger = Logger.getLogger(MyClass.class); 

這是因爲它可以讓你微調您的應用程序內的模塊(包),甚至個別班級日誌行爲一個很好的做法。因此,您可以禁用某些軟件包的日誌記錄,在其他軟件包中以INFO級別登錄,並在某些關鍵類別上登錄DEBUG級別。當你想抓到一個錯誤。

B)但是,如果你要到處一個記錄器,只需使用根記錄在每一個類:

private static final Logger logger = Logger.getLogger(); 

C)將呼叫不太複雜的方法,性能差異可能是微不足道的,因爲無論如何,JIT編譯器會積極地內聯調用。對於複雜的方法,這更多的是一個開放的問題。

請注意,您顯示的方法通過加載記錄器配置完成不必要的工作 - 如果您將配置文件log4j.properties命名並放在類路徑中,則由Log4J自動完成。但是,即使您需要使用非標準配置文件名,仍可以在啓動時將Log4J配置加載到一個位置,並省略記錄器的延遲加載。那麼剩下的是

private static final Logger logger = Logger.getLogger(ExtractData.class); 

private static Logger getLogger() { 
    return logger; 
} 

並且這肯定會被編譯器內聯。儘管如此,您仍可以保留getLogger,以避免修改大量來電顯示代碼。

請注意,getLogger不需要爲public,因爲無論如何所有類都應該有自己的記錄器引用。

0

每個類都可以得到它自己的記錄作爲

final static private Logger log = Logger.getLogger("com.company.package.MyClass"); 

這使您可以通過類來調整log4j的設置,這比標準記錄器更加靈活。

3

答)取決於,但我認爲每類記錄器的粒度是使用log4j的效用的一部分。您可以重定向來自一個類的日誌信息,或者將它們全部發送到同一個文件。B)你不會傳遞一個記錄器,你只需要使用Logger.getLogger()方法來使用根記錄器。

C)在性能方面可能不大。如果它不是靜態的,則可以選擇將getLogger()方法表示爲final以表明它應該內聯。彼得的回答在這裏更好,正如他所指出的那樣,如果方法很簡單,反正它可能會被內聯。

+0

re C:getLogger()已經是靜態的,因此使其成爲多餘的。 – 2010-06-14 14:44:12

+0

@Mike謝謝,你說得對。 – 2010-06-14 14:46:02

+0

無論如何聲明一個(非靜態)方法'final'並不重要--JIT編譯器_knows_是否在實際上下文中被重寫,因此它可以相應地內聯。 – 2010-06-14 14:51:47

相關問題