應該將記錄器聲明爲靜態還是不是?通常我看到兩種類型的聲明爲Logger:應該將記錄器設置爲靜態還是不需要
protected Log log = new Log4JLogger(aClass.class);
或
private static Log log = new Log4JLogger(aClass.class);
哪一個應該被使用?什麼是兩者的贊成和反對?
應該將記錄器聲明爲靜態還是不是?通常我看到兩種類型的聲明爲Logger:應該將記錄器設置爲靜態還是不需要
protected Log log = new Log4JLogger(aClass.class);
或
private static Log log = new Log4JLogger(aClass.class);
哪一個應該被使用?什麼是兩者的贊成和反對?
非靜態形式的好處是,你可以在一個(抽象)基類,而不必擔心正確類名稱將用於類似如下聲明它:
protected Log log = new Log4JLogger(getClass());
但是它的缺點是很明顯的是將爲每個類的實例創建一個全新的記錄器實例。這本身可能並不昂貴,但是會增加很大的開銷。如果您想避免這種情況,您想使用static
表單代替。但是它的缺點是你必須在每個單獨的類中聲明它,並在每個類中注意在記錄器的構造過程中使用了正確的類名,因爲getClass()
不能在靜態上下文中使用。但是,在平均IDE中,您可以爲此創建一個自動完成模板。例如。 logger
+ ctrl+space
。另一方面,如果您通過工廠獲取記錄器,而工廠又可以緩存已經實例化的記錄器,那麼使用非靜態的表單不會增加太多的開銷。爲此,Log4j例如有一個LogManager
。
protected Log log = LogManager.getLogger(getClass());
在抽象類中聲明'abstract Log getLogger();'。實現此方法,爲特定實例返回靜態記錄器。將'private final static Log LOG = LogManager.getLogger(Clazz.class);'添加到您的IDE類模板中。 – 2012-09-05 08:45:45
對於slf4j:'protected Logger log = LoggerFactory.getLogger(getClass());' – 2014-12-18 11:18:20
@BalusC將getClass()傳遞給getLogger方法的問題在於它返回當前實例的類。通常情況下,日誌更需要與代碼所在的類相關聯。例如,如果日誌記錄代碼在Parent類中,那麼即使執行實例是Parent的子類Child的實例,我們也希望日誌記錄與Parent相關聯。使用getClass()它將與子項關聯,錯誤地 – inor 2018-02-26 11:31:38
最重要的區別是它如何影響你的日誌文件:日誌去哪個類別?
還有就是你的第一種情況的變體:
保護的登錄日誌=新Log4JLogger(的getClass());
在這種情況下,您的日誌類別表示記錄的代碼正在處理哪個對象。
在您的第二個選擇(私有靜態)中,日誌類別是包含日誌代碼的類。所以通常是正在做記錄事情的類。
我強烈建議最後一個選項。與其他解決方案相比,它具有以下優點:
它也有缺點:
我曾經認爲所有的記錄器應該是靜態的;然而,this article at wiki.apache.org帶來了一些關於類加載器泄漏的重要內存問題。將記錄器聲明爲靜態可防止聲明類(和關聯的類加載器)在使用共享類加載器的J2EE容器中被垃圾收集。如果重新部署應用程序足夠多次,這將導致PermGen錯誤。
我真的沒有辦法解決這個類加載器泄漏問題,除了聲明記錄器是非靜態的。
我懷疑靜態字段也會有內存泄漏問題。正如其他人所說,非靜態可能會有性能問題。那麼理想的方式是什麼? – liang 2013-10-08 07:26:39
@piepera在你引用的文章中描述的主要問題是,當「考慮使用」private static Log log =「的類通過多重祖先的ClassLoader部署時,可以控制每個應用程序中的日誌級別據稱是獨立的「應用程序」「。我不認爲這是一個問題,因爲在這種特殊情況下,應用程序有一個「共同點」,並且「共同點」決定了該類的日誌級別,是的,它適用於所有應用程序......但保留記住這個類在這些應用程序之外[加載] – inor 2018-02-20 16:21:45
伐木是一個橫切關注。使用方面,問題是沒有意義的。 – 2010-10-03 05:26:23
'static'是每個類的一個參考。非靜態**是每個實例**一個參考**(+初始化)。所以在某些情況下,如果你有很多實例,後者會對內存產生重大影響。切勿在*頻繁*對象中使用非靜態。我總是使用靜態版本。 (應該是* uppercased *'LOG') – 2012-09-05 08:43:29
如果你使用[jcabi-log](http://www.jcabi.com/jcabi-log/),一個靜態的包裝器,你可以根本不需要這個變量slf4j – yegor256 2012-10-05 07:19:37