2012-04-18 22 views
11

我正在寫一個遊戲引擎/庫,其中我有一個事件調度程序類,它通過調用「已註冊」事件處理程序類的偵聽器方法來調度事件。可以通過調用適當的調度程序方法向事件調度程序註冊事件處理程序/偵聽程序。將代碼添加到具有Instrumentation的Java類:ASM或BCEL?

這顯然會導致註冊每個事件處理程序的一些樣板代碼(以及我的引擎的其他方面都有類似的bolierplate代碼),所以我想知道 - 如何使用Instrumentation在加載期間添加所有必需的代碼的事件處理程序類,因此編碼時不需要顯式註冊與事件分派器 - 當程序運行時,調度程序的註冊方法調用會自動添加。

我的理解是,爲了使用Instrumentation,應該使用一些字節碼修飾符API。我知道兩個 - ASM和BCEL。我應該使用哪一個?顯然,這是一個我想要做的簡單任務,所以我想要一個更容易學習和更好記錄的任務。

編輯:這裏是一個具體的例子。

原始事件處理類:

@Handler //indicates this this class should be transformed 
public class MouseEventHandler implements EventHandler<MouseEvent> 
{ 
    //hidden default constructor 
    public void handleEvent(MouseEvent event) 
    { ... } 
} 

改造後:

@Handler 
public class MouseEventHandler implements EventHandler<MouseEvent> 
{ 
    public MouseEventHandler() 
    { 
     //add this line of code to default constructor 
     Game.getEventDispatcher().addEventHandler(this); 
    } 
    public void handleEvent(MouseEvent event) 
    { ... } 
} 

回答

20

然而,我會考慮其他選項之前,跳轉到字節碼操縱。

+0

bcel已經包含到JDK – 2013-07-09 06:53:07

+1

@ alexander.box:是的,作爲XSLTC變壓器Xalan的依賴項,但它是非標準的API,也隱藏在包com.sun.org.apache.bcel.internal !更好地提供你自己的罐子。 – Daniel 2014-07-08 08:25:47

+2

哦,雖然我在這上面:當班級必須裝備時,ASM是一個非常好的選擇。易於理解和使用。還有一個非常好的文檔。 – Daniel 2014-07-08 08:26:16

6

將邏輯添加到幾個類中可能會很無聊,但除非你擁有處理程序,否則就是這樣。 保持簡單

這就是說,

Game.registerHandler(this); 

會更加面向對象的。

在每個類中添加邏輯的替代方案是引入一個工廠,該工廠負責實例化處理程序。

HandlerFactory.createMouseHandler(); 

和方法createMouseHandler包含有類似

Handler mh = new MousheHandler(); 
registerHandler(mh); 
return mh; 

如果你不想這些選項,我會考慮任何一個方面的框架(也許AspectJ的)或反演一個容器控制(也許是Spring IoC)。方面允許您註釋您的來源,並在選定的地方「編織」代碼。 IoC容器允許您控制對象的生命週期(例如實例化)。兩者都在場景後面使用字節碼檢測。

但是,如果你想自己做儀器,我只能比較我個人使用的Javassist和ASM。

ASM是低級的,並且真正在java字節碼的級別上運行。你必須熟悉它。該框架設計得非常好,手冊非常好,而且它是一個很棒的圖書館。一方面,替換字節碼的模式可能會變得複雜,因爲它需要所謂的「有狀態」轉換。另一方面,您可以完全控制字節碼。

Javassist更高級。您不會以字節碼的原始級別進行操作,這是略高的級別,例如字段讀/寫,消息發送,構造函數。此外,它允許您使用常規Java語法指定更改,然後由框架進行編譯。該API有點混亂,因爲這個項目多年來一直在增長。有關於框架的文檔,但與ASM不太一樣。