簡體   English   中英

如何用注釋處理器替換GWT.create?

[英]How can I replace GWT.create with an Annotation Processor?

我想創建一個注釋處理器,以替換對GWT.create的調用。

使用注釋處理器,您必須生成兩個類,然后根據上下文動態地(在運行時)在它們之間進行選擇(您可以生成一個工廠來幫助實現此目的,但是您仍然必須以某種方式來填充工廠當前上下文(例如當前語言環境)。

來源: https//stackoverflow.com/a/29915793/116472

我運行了注釋處理器,它很好地生成了類。 我不知道的部分是運行時選擇部分。

如何選擇運行時?

我假設您已經涵蓋了代碼生成方面,僅關注我們如何選擇GWT中的正確實現:

但您仍必須以某種方式將當前上下文(例如當前語言環境)提供給工廠。

我們可以按照您的建議在運行時執行此操作,但是從最近添加的對System.getProperty支持開始,您也可以在編譯時執行此操作。

當然,第一步是為您可能希望訪問的每個實現生成代碼。 以語言環境為例,您可能具有Foo_en.javaFoo_es.javaFoo_de.java等。

接下來,我們需要一種一致的方法來獲得任何一種實現-可能是使用類似這樣的方法生成的FooFactory

public static Foo getFoo(String locale) {
  if ("en".equals(locale)) {
    return new Foo_en();
  } else if /*...
  ...*/

  throw new IllegalArgumentException("Locale " + locale + " is not supported");
}

如果在運行時詢問用戶他們想要的語言環境,則可以將該值傳遞給此工廠方法以獲得所需的實現。 同樣,如果您可以在運行時從某個值讀取該值,則可以再次獲取正確的實例並繼續進行操作。


但是,如果您實際上想讓編譯器為您選擇呢? 讓我們保留由注釋處理器生成的代碼,但將選擇語言環境的階段移至編譯器及其排列。

與現有的GWT代碼中一樣,為區域設置指定屬性,並指定多個值。 然后,與其詢問用戶或在運行時在自己的Java代碼中確定所需的語言環境,不如使用GWT通常使用的選擇腳本連接(檢查url,cookie,元標記,用戶代理本身,等等)-您可以根據需要為此構造自己的property-provider

和以前一樣,我們可以使用getFoo(locale) ,但是現在我們使用System.getProperty讀取在.gwt.xml文件中創建的屬性。 對於每個排列,它將被靜態編譯為正確的常數。 但是,而不是每次需要實例時都調用FooFactory.getFoo(System.getProperty("locale")) ,而是在生成的FooFactory中創建另一個方法:

public static Foo getFoo() {
  return getFoo(System.getProperty("locale"));
}

現在,我們只需調用FooFactory.getFoo() ,就可以為當前的排列獲取正確的類。


Dagger問題:Thomas可能更適合解決此問題,但是不,Dagger2不像Guice那樣執行bind(Foo).to(Bar).in(Scope) ,因為那將需要運行代碼來解析綁定,而Dagger僅通過反映類型來從其可見的角度進行操作,而不實際運行代碼。 這意味着您最終會遇到很多@Provides方法,或者在實際類型上加上應用於實現內容的詳細信息。

FWIW到目前為止,由於一些怪癖需要我重新考慮一些問題,因此我沒有采用Dagger,並且我還沒有花時間進行重新思考:

首先,您沒有被迫替換 GWT.create()調用。 由於GWT生成器執行2件事,因此您可能(並非總是可能)用注釋處理器替換代碼生成部分,並用簡單的<replace-with>規則(已生成的目標類) <replace-with> “選擇”部分。由注釋處理器)。
還要注意,實際上,可以使用ServerGwtBridge在GWT上下文之外(例如,在服務器端)使用GWT.create() ,讓您注冊類實例化器。 注釋處理器可以生成這樣的實例化器,或者您可以使用反射對其進行編碼。

如果確實要替換GWT.create()調用,則必須使用工廠(直接在調用點處,或包裝到外觀/代理中)。 該工廠也可以由注釋處理器生成。

與任何此類工廠一樣,代碼將是if…else級聯或switch…case ,以最終new適當的(生成的)類。 但條件非常適合您的需求。

在GWT上下文中,您可以使用GWT.create(UserAgent.class).getCompileTimeValue()訪問user.agent綁定屬性值,從而替換<when-property-is name="user.agent" value"…" /> *.gwt.xml <when-property-is name="user.agent" value"…" />帶有一個switch…case (請注意,然后您必須自己處理回退;例如,當沒有規則特別匹配ie9時, ie9退回到ie8 )。 其他值得注意的值是LocaleInfo.getCurrentLocale() ,以代替locale綁定屬性(但注釋處理器不太可能知道該屬性的所有可能值,除非您將其作為選項傳遞或處理器讀取GWT模塊文件,您可能還必須將其名稱作為選項傳遞)。 LocaleInfo.getCurrentLocale().isRTL()更有趣。 您還可以使用GWT.isClient()類的東西或Window.Navigator屬性; 從GWT 2.8開始,您可以使用System.getProperty()來訪問您的配置和綁定屬性(例如System.getProperty("user.agent", "unknown") )。 最后,當然,還有JSNI可以檢測當前瀏覽器支持的功能。 但是隨后該代碼無法由GWT編譯器優化,並且所有生成的類都將在最終JS中進行編譯。

當您不能使用此類靜態值時,仍可以將相關上下文作為參數傳遞給工廠。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM