[英]How can I replace GWT.create with an Annotation Processor?
我想創建一個注釋處理器,以替換對GWT.create
的調用。
使用注釋處理器,您必須生成兩個類,然后根據上下文動態地(在運行時)在它們之間進行選擇(您可以生成一個工廠來幫助實現此目的,但是您仍然必須以某種方式來填充工廠當前上下文(例如當前語言環境)。
– 來源: https : //stackoverflow.com/a/29915793/116472
我運行了注釋處理器,它很好地生成了類。 我不知道的部分是運行時選擇部分。
如何選擇運行時?
我假設您已經涵蓋了代碼生成方面,僅關注我們如何選擇GWT中的正確實現:
但您仍必須以某種方式將當前上下文(例如當前語言環境)提供給工廠。
我們可以按照您的建議在運行時執行此操作,但是從最近添加的對System.getProperty
支持開始,您也可以在編譯時執行此操作。
當然,第一步是為您可能希望訪問的每個實現生成代碼。 以語言環境為例,您可能具有Foo_en.java
, Foo_es.java
, Foo_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.