2012-09-19 28 views
4

繼續發佈此處的問題:Can you find all classes in a package using reflection?我開始使用反射庫來查找給定類型的子類的所有類。源代碼看起來像這樣,從一個問題的鏈接SO問題:Java的思考庫:查找包中的所有類

Reflections ref = new Reflections(new ConfigurationBuilder() 
    .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner()) 
    .setUrls(ClasspathHelper.forPackage("org.somepackage")) 
    .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("org.somepackage")))); 

ref.getSubtypesOf(Object.class); 

然而,東北角使用此代碼一段時間後,我才發現,原來它只會發現,子類中的另一類型類這個包。它不會找到從其他用戶定義的軟件包中派生出的從外部定義的類的子類的類。

我不知道如何解決這個使用反射庫。我希望所有將它們的包聲明爲'org.somepackage'的類,而不管它們的超類是什麼。任何幫助?

回答

6

我寫了一個名爲Rebound的庫(與Reflections相反),它搜索給定類型和包前綴的子類。如果將前綴設置爲空,它將搜索類路徑下的每個類,例如

import gigadot.exp.reflects.core.Processor; 

Rebound r = new Rebound(""); 
Set<Class<? extends Processor>> classes = r.getSubClassesOf(Processor.class); 

但是你應該小心,因爲在classpath中搜索所有東西是一個緩慢的過程。

這個庫比Reflections簡單得多,可能不會做你想做的。我提交錯誤報告時,由於我的沮喪,我寫了這些,但沒有人嘗試解決問題。

+0

這看起來很有希望。我不需要執行很多這樣的調用,但是它們完全詳盡至關重要。謝謝你,我會研究這個。 – mtrc

+1

編輯 - 是否在任何地方列出Rebound的依賴關係,例如log4j的? – mtrc

+0

對,得到這個工作 - 完全按照需要工作。感謝你這樣做,你真的保存了一天。我現在可以回家了! – mtrc

0

在我的情況下,這段代碼可以很好地加載外部API的類,但不知道爲什麼它不適用於像'java.util'這樣的內置包。

Reflections reflections = new Reflections(new ConfigurationBuilder() 
       .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner()) 
       .setUrls(ClasspathHelper.forClassLoader(classLoadersList.toArray(new ClassLoader[2]))) 
       .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("org.reflections")))); 
2

這樣做的原因是,

ref.getSubtypesOf(Object.class); 

只返回對象的直接子類。如果你想從一個掃描包得到所有的類,你應該做到以下幾點:

Reflections ref = new Reflections(new ConfigurationBuilder().setScanners(new SubTypesScanner(false), new ResourcesScanner(), new TypeElementsScanner()) 
... 
Set<String> typeSet = reflections.getStore().getStoreMap().get("TypeElementsScanner").keySet(); 
HashSet<Class<? extends Object>> classes = Sets.newHashSet(ReflectionUtils.forNames(typeSet, reflections 
      .getConfiguration().getClassLoaders())); 

這可能看起來有點hackish的,但它是我迄今發現的唯一途徑。 下面是對這個功能的一些解釋: 當掃描完成反射時,它將所有元素放在一個多值圖中。在我所粘貼的代碼示例,結果把一個地圖內使用下列按鍵:

SubTypesScanner, ResourcesScanner, TypeElementsScanner 

的ResourceScanner排除具有的.class結尾的文件。 TypeElementsScanner是一個帶有一個鍵的映射,該鍵包含一個類的名稱和一個字段的值等。因此,如果您只想獲取類名,則基本上獲得密鑰集,然後將其轉換爲集如果類。 SubTypesScanner也是一個映射,具有所有超類(包括對象和接口)和值的關鍵 - 實現/擴展這些接口/類的類。通過遍歷鍵集並獲取所有值,您也可以使用SubTypesScanner,但是如果某個類實現了一個接口,則必須處理重複的實體(因爲每個類都會擴展Object)。

希望有所幫助。

+0

不知道爲什麼沒有人對這種方法進行過嘗試/反饋,它對我來說效果很好。謝謝! – juanmf

+0

'HashSet > classes'爲空(不知道爲什麼),但'Set typeSet'包含正確的類名。 – juanmf