2012-04-01 35 views
0

假設我有這個註解搜索特定註釋類型的所有實例

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface Name 
{ 
    String value(); 
} 

這是怎麼回事如下

@Name("name1") 
public static Foo foo = new Foo(); 

我的這些倍數在我的項目源文件使用。是否有一種相當簡單的方法來搜索和收集所有那些之前有@Name的「foo」? 換句話說,我想寫一個方法,將返回一個Set<Foo>包含這些。

謝謝!

+0

在java中?使用find + grep – ControlAltDel 2012-04-01 00:16:11

+0

@ user1291492,使用unix cmd行應該非常容易,保留時間爲RUNTIME。該方法可能會或可能不會訪問源代碼。 OTH,也許這個類文件是可以greppable的。 – emory 2012-04-01 05:18:15

+0

稍有偏離主題,但你爲什麼要'Set '。有一個'Map '或名稱的重點似乎更有意義。 – emory 2012-04-01 05:20:49

回答

2

我對其他人建議的類路徑掃描程序並不熟悉。他們看起來像一個強大的,如果不是理想的解決方案。

如果您可以控制源,那麼您可以使用註釋處理。

創建一個註釋處理器,該註釋處理器將創建一個具有靜態成員Map<String,Foo>的類 - MapClass。註釋處理器每次遇到@Name註釋時,都會將其添加到源代碼MapClass。當它完成處理註釋時,它將具有與硬編碼地圖相同的效果。

註釋處理髮生在編譯期間。如果項目中的某些類不是由您編譯的。例如,如果其他人編譯一些類並給你一個罐子,那麼它不會很容易工作。但是,如果所有的類都由您編譯,那麼它不應該是一個問題。

要創建註釋處理器,請擴展AbstractProcessor。您需要使用@ SupportedAnnotationTypes ("Name")批註註釋您的課程(確保名稱是註釋的完全限定名稱。

覆蓋process方法。 process有兩個參數:annotationsroundEnvannotations只是這個特定處理器支持的一組註釋 - 在你的情況下它應該是(Name)。 roundEnv是一個有用的工具類。

迭代annotations中的一個註釋。使用roundEnvgetElementsAnnotatedWith。這應該給你帶有@Name註釋的所有元素的集合。

AbstractProcessor還有另一個實用程序成員 - processingEnv。使用其getFiler方法createSourceFile

然後你必須稍微修改一下你的編譯。您必須分別在其他課程之前編譯處理器。在編譯處理器並編譯其他類之後,必須告訴編譯器關於處理器的信息。如果您正在使用命令行,則可以添加-processorpath /path/to/processor/class[es]-processor qualified.name.of.processor

這種方法優於類路徑掃描程序的優點是,所有事情都發生在編譯時。例如,如果您不小心將一個@Name註釋添加到Bar元素,則可以讓處理器發出編譯時錯誤(如果希望處理器可以忽略它)。然後你可以在產品發貨前修好它。使用類路徑掃描程序時,拋出的任何錯誤都是運行時錯誤 - 用戶將看到。

這種方法的缺點是,一切都發生在編譯時。這使得向項目動態添加類變得更加困難。

+0

這聽起來像我需要的。但是註釋處理器到底是什麼樣的?我不確定它是如何「遇到」@Name註釋的?它不會需要做一些掃描找到那些? – user113454 2012-04-01 06:40:31

+0

請您詳細說明一下嗎?謝謝 – user113454 2012-04-01 07:58:46

+0

@ user1064918我希望有所幫助。我認爲最大的區別是,類路徑掃描器更強大 - 它只會工作。但是如果你的項目合適,使用註釋處理器可能更合適。 – emory 2012-04-01 17:32:18

0

不是真的(不是來自代碼)。 一個解決辦法是把他們都在一個類,然後在類的Field S(getFields())迭代,並檢查Annotation S(getAnnotation()

1

你需要的是一個classpath的掃描儀。我用Metapossum Scanner(它贏得了,因爲它在mvn回購)掃描註釋類,但我不認爲它會掃描註釋的字段。

我看着的其他選項是Reflections。我沒有使用反射,只研究它。該文檔有一個getFieldsAnnotatedWith查詢,這似乎是你需要的。

要預先警告,Classpath掃描儀是非常流行的,並且在您的Classpath中擁有更多的功能。

0

你可能想看看Scannotation!它可能會解決你的問題!

Scannotation是一個Java庫,它從一組.class文件創建一個註釋數據庫。這個數據庫實際上只是一組索引,用於索引使用哪些註釋以及哪些類正在使用它們。

PS .: VRaptor framework內部使用!

相關問題