2011-11-03 40 views
3

JDK 6和7(不是來自5的apt工具API)中的Java註釋處理API定義了註釋處理器的生命週期。其中一個通過無參數構造函數實例化,init方法通過ProcessingEnvironment實例調用,然後通過process方法使用該處理器。如果適用,只有一個處理器實例在整個後續處理循環中製作和使用。跨編譯輪次的處理環境成員的一致性

由於我的處理器類變得有點臃腫,我創建了它應該處理的單獨註釋的處理程序類。在這些類的方法中,我總是通過ElementsTypes傳遞我從ProcessingEnvironment獲得的實用方法的實例。這使我的方法簽名相當長。

我寧願在處理程序中以及在處理器實例中保留對ElementsTypes實例的引用。我通過將ProcessingEnvironment傳入init方法來完成此操作。現在,我想知道這是否安全。對於Processor的JavaDoc明確指出某些方法僅針對處理器調用一次,但此處未提及init。我有點認爲這是隱含的理解,但我不是100%確定的。

我也想知道,Messager實例,也可以從ProcessingEnvironment獲得,並且在所有處理循環中保持不變。我寧願沒有警告/錯誤從一輪出現,但其他人被排除在外。我有理由相信,在各輪中使用相同的實例應該是安全的,但只是想確定一些。

回答

2

我問過自己同樣的問題,並決定始終使用init提供的當前回合的ProcessingEnvironment的實用程序。使用javac似乎沒有任何區別,但還有其他註釋處理工具可能會顯示不同的行爲。我已經經歷了javac中的處理工具和eclipse所使用的工具之間的一些區別,所以我在處理文檔時沒有明確指出任何事情。問題是,你想測試所有現有的處理工具嗎?

另外,我認爲如果那些處理助手工具是不會改變的,它們將是處理器構造函數的參數。

+0

好點...我不知道爲什麼他們不只是通過構造函數傳遞的,而是要經過一些init方法。設計約束,也許?無論如何,我在初始化初始化處理程序並給他們參考保存的實用程序。如果init被多次調用,會有點問題......我不能讓處理程序被替換,因爲它們保持了各個狀態的狀態。也許我可以讓init更新處理程序的工具參考。由於Eclipse的警告,你給了我一些想法。 –

1

這可能是值得一提的是,AbstractProcessor(這是由javadoc of the Process class因爲這可能被實現者使用的子類建議)拋出IllegalStateException如果init method被稱爲不止一次。

這並不意味着傳遞的ProcessingEnvironment無法在隨後的getter調用或不同的回合中返回不同的值,儘管它不是傳統的。無論如何,它可能是值得的process方法的開始檢查:

private ProcessingEnvironment processingEnv; 
private Elements elementUtils; 
private Types typeUtils; 

public Processor() { 
} 

@Override 
public synchronized void init(final ProcessingEnvironment processingEnv) { 
    this.processingEnv = processingEnv; 
    elementUtils = processingEnv.getElementUtils(); 
    typeUtils = processingEnv.getTypeUtils(); 
} 

private void checkEnvironmentChange() { 
    checkSame(elementUtils, processingEnv.getElementUtils(), "elementUtils"); 
    checkSame(typeUtils, processingEnv.getTypeUtils(), "typeUtils"); 
} 

private <T> void checkSame(final T object1, final T object2, final String name) { 
    if (object1 != object2) { 
     throw new IllegalStateException(name + " should not change"); 
    } 
} 

@Override 
public boolean process(final Set<? extends TypeElement> annotations, 
     final RoundEnvironment roundEnv) { 
    checkEnvironmentChange(); 
    ... 
} 
+1

這非常有趣。每個編譯只有一個處理器,並且init只能在缺省抽象實現中調用一次。至少可以解決這個問題。正如您所建議的那樣,檢查是否返回不同的值可能不是一個好主意。我已經有一段時間了,因此我不記得它是否真的會成爲一個問題......我想,這取決於保留的對象是否有像樣的重寫equals方法。 –