2009-10-28 45 views
5

假設,我有很多類,它們是使用Java反射構造的(出於某種原因)。現在我需要將值後注入字段,這些字段是 ,註釋號爲@PostInjectJava:什麼是使用反射注入字段的最快方法?

public class SomeClass { 
    @PostInject 
    private final String someString = null; 

    public void someMethod() { 
    // here, someString has a value. 
    } 
} 

我的問題是:什麼是快速的方式使用反射來設置字段?
請記住,我需要經常在很多課程上這樣做,這就是爲什麼性能是相關的 。

我會憑直覺做的就是通過這個僞代碼所示:

  • 獲取類
    clazz.getFields();
  • 檢查的各個領域,這是注有@PostInject
    eachField.getAnnotation(PostInject.class);
  • 使這些字段可訪問
    eachAnnotatedField.setAccessible(true);
  • 將它們設置爲一定值
    eachAnnotatedField.set(clazz, someValue);

恐怕讓所有領域,是做最慢的事情。
當我從一開始就知道它時,我可以有人獲得一個領域嗎?

注:我不能讓這些類實現一些接口,這將允許使用方法設置字段 。我需要 POJO。

注2:爲什麼我想要post-field注入:從API用戶的角度來看,它必須可以使用final字段。此外,當API先驗地不知道字段的類型和數量時,使用接口不可能實現字段初始化。

NOTE2b:從視用戶的角度來看,最終的合同是破碎。它保持最終狀態。首先,一個字段被初始化,然後它不能被改變。順便說一句:有很多API使用這個概念,其中一個是JAXB(JDK的一部分)。

+0

我只是好奇你爲什麼需要這樣做?這個背後有一個有趣的故事,如果有,你能分享嗎? – 2009-10-28 12:10:49

+0

我正在編寫一個類似於JAXB的編組器,但更特別(因此更受限制)。帶註釋的POJO非常靈活。 – 2009-10-28 12:21:17

+1

如果你要求實現者使用你的註釋 - 你在這裏並沒有真正獲得使用接口的任何東西 - 並且你沒有真正使用POJO - http://en.wikipedia.org/wiki/Plain_Old_Java_Object#Contextual_variations – Nate 2009-10-28 12:50:15

回答

7

在構建對象並保存您在對象本身中獲得的註釋字段集合或保留一組單獨的類到註釋字段集合之後,如何執行步驟1到3?

然後,當你需要更新注入的領域中的對象,無論從對象或單獨的地圖檢索設定和執行步驟4.

+0

完美的主意! – 2009-10-28 12:18:13

1

+1我喜歡RSP的想法。


另一個選擇,正如你所說,你知道從一開始就關注的幾個領域,就是隻問這些領域或方法。

舉例:詳見getDeclaredMethodgetDeclaredFieldjava/lang/Class.html

1

不知道,如果它的任何好處,但this project看起來像它會做你想要什麼。報價:

一組反射公用事業和 相關 雜公用事業類和各自領域的 沒有依賴關係是 與Java 1.5和泛型兼容工作。

公用事業緩存反射數據 高性能操作,但使用 弱/軟緩存以避免 保持開放類裝入器並且使得所述 在內存中緩存 存在永久。支持使用您自己的緩存機制覆蓋 的能力是 。

0

您可以利用現有的框架允許注入對象構造的依賴關係。例如Spring allows to do that與aspectj編織。總體思路是,你可以在spring層次上定義bean的依賴關係,並且只標記目標類,以便爲他們的對象創建提供建議。實際的依賴關係解析邏輯直接注入類字節碼(可以使用編譯或加載時編織)。

0

用反射做任何事情的最快方法是儘可能緩存實際的Reflection API類。比如我最近做了一個尚未另一 - 動態POJO的手,我相信是這些東西大家都結束了在某些時候它使我做這件事做一個:

Object o = ... 
BeanPropertyController c = BeanPropertyController.of(o); 

for (String propertyName : c.getPropertyNames()) { 
     if (c.access(propertyName) == null && 
      c.typeOf(propertyName).equals(String.class)) { 
       c.mutate(propertyName, ""); 
     } 
} 

它的工作方式是它基本上具有一個控制器對象,它可以延遲加載bean的所有屬性(注意:涉及的一些魔法),然後只要實際控制器對象處於活動狀態,就可以重用它們。我只能說,通過保存Method對象本身,我設法將這件事情變成了一件該死的事情,我爲此感到非常自豪,甚至考慮釋放它,假設我能夠設法解決版權問題等。

相關問題