2012-04-18 21 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不太一样。