2013-02-19 57 views
6

我通常定義記錄是這樣的:如何使用谷歌吉斯注入記錄

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

但使用@Inject的時候一定要使用非靜態和非最終場,如:

@Inject 
private Logger logger; 

即記錄器將在該類的每個實例中創建,並且記錄器也是可變的。可能存在一些使記錄器靜態的方法?還我怎麼可以綁定記錄到某一類(我用創建記錄對象時,從工廠LoggerFactory.getLogger(MyClass.class);,派類對象如何在使用注射同樣的方式記錄?)?

+2

記錄器被注入的原因是什麼?僅僅是爲了避免一些打字? – 2013-02-19 09:58:27

回答

7

請檢查吉斯維基Custom Injections,有一個完整的Log4J的例子。

編輯:您可以使用static字段或final字段爲您的記錄器,但不是static final之一。這是一個Java limitation

還應該小心that:不建議

注入最終字段,因爲注入的值可能不是其他線程可見。

沒有測試過這一點,但在本文中的代碼應該工作正常進行靜態字段,但是你可以通過擺脫MembersInjector的,做這一切在TypeListener(因爲靜態字段需要改進只設置一次)。

使用requestStaticInjection()將迫使你列出所有的類都在一個模塊文件 - 不是一個好主意,因爲你很快就會忘記添加一個。如果你只是想支持JUL,你可能會更好的使用built-in support(正如傑夫所說,我認爲你不想得到一個普遍的答案,因爲你沒有在你的問題中具體提到JUL)。

+0

我發現鏈接文章缺乏幾個方面:1)需要新的註釋。對於JUL,你可以使用@Inject(java.inject.Inject和Guice的一個)。 2)不支持構造函數注入,3)不支持方法注入4)只有註釋中的黑客支持超類。總結到目前爲止:JUL的支持是特殊的,不能以相同的方式和質量轉移到其他日誌框架。 – 2013-02-22 23:21:34

+0

對不起,我發現這對我的anwser來說並不具有建設性或相關性。 1)不,不是你可以放下支票並注入所有記錄器字段 2)是的,但你如何期望與Guice合作? 3)支持,你可以用任何你想要的方式檢查課程(例如尋找方法) – 2013-02-23 13:34:34

+0

我的觀點與你的答案有關,它是這樣的:鏈接的文章有其缺點。那裏提出的解決方案不支持注入,Guice支持其他地方的注入。這些差異應該清楚,而不是事後。特別是作爲問題的最後部分(「如何創建...」)和使用@ @ Inject似乎恰恰解決了這個IMO問題。
我將這三個問題命名爲類似案例。這不是針對你,而是針對每個想要探索這個解決方案的人 - 如果他們說「我可以接受這些東西」。好的 - 歡迎。 – 2013-02-23 16:31:45

2

當設計你的依賴注入的應用程序,通常最好的做法是避免靜態字段和儘可能多的方法。這樣你的依賴關係就更清晰了,因此在測試期間以及隨着應用程序的發展,用其他實例替換真正的依賴關係會更容易。因此,理想的行爲是儘可能避免靜態方法和字段(包括記錄器)。

吉斯,但是,並允許標記域靜態和requesting injection of static fields when the Injector is created。這些字段需要保持不變 - final並不意味着「除Guice外最終」。

public class YourClass { 
    @Inject static Logger logger; 

    /* ... */ 
} 

public class YourModule extends AbstractModule { 
    @Override public void configure() { 
    /* YourClass.logger will work once you create your Injector. */ 
    requestStaticInjection(YourClass.class); 
    } 
} 

吉斯自動爲您提供java.util.logger.Logger instances嵌入到它的類名,但是這只是因爲a special case coded into Guice。如果你想有一個特殊的記錄,如this SO question,你需要調查的自定義注射到的Jakub鏈接 - 但如果整個目標就是集中採集器創建,因此您可以在一個地方控制它,你可以說重構進入Guice以外的靜態工廠。

@LogToFile 
public class YourClass { 
    private static final Logger logger = YourLoggerFactory.create(YourClass.class); 

    /* ... */ 
} 

public class YourLoggerFactory { 
    private YourLoggerFactory { /* do not instantiate */ } 

    public Logger create(Class<?> clazz) { 
    if (clazz.getAnnotation(LogToFile.class) != null) { 
     return someImplementation(new File(...)); 
    } else { 
     return someOtherImplementation(); 
    } 
    } 
} 
+0

您的解決方案的缺點是必須在所有應用程序中以一致的方式提供類中的名稱Yourclass.class。這可能恰恰是集中注射被認爲是有益的原因之一 - 這種問題在適當的注射支持下不會存在。 – 2013-02-22 23:24:31

+0

@ A.H。請注意,供應商或依賴關係確定其注入網站的能力[明確且故意拒絕作爲功能](https://code.google.com/p/google-guice/issues/detail?id=27)。在實例字段中,可以使用'this',但在靜態上下文中,Java可惜沒有比類名本身短的語法。當您找到或創建「正確的注射支持」時,請將其傳遞下去 - 我很高興看到它的工作原理! – 2013-02-23 00:19:45

+0

請注意,Guice *確實*允許注入最終字段,請參閱我上面的答案以獲取鏈接。 – 2013-02-23 16:29:56