12

我正在编写一个游戏引擎/库,其中我有一个事件调度程序类,它通过调用“已注册”事件处理程序类的侦听器方法来调度事件。可以通过调用适当的调度程序方法向事件调度程序注册事件处理程序/侦听器。

这显然会导致一些用于注册每个事件处理程序的样板代码(并且我的引擎的其他方面也有类似的样板代码),所以我想知道 - 在加载事件处理程序期间使用 Instrumentation 添加所有必要的代码怎么样类,因此在编码时不需要向事件调度程序显式注册 - 对调度程序的 register 方法的调用会在程序运行时自动添加。

据我了解,为了使用 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)
    { ... }
}
4

2 回答 2

25

Java字节码库:

但是,在开始字节码操作之前,我会考虑其他选项。

于 2012-04-18T08:31:00.947 回答
6

将逻辑添加到几个类可能很无聊,但除非你有成千上万的处理程序,否则我会这样做。保持简单

也就是说,

Game.registerHandler( this );

会更加面向对象。

在每个类中添加逻辑的另一种方法是引入一个负责实例化处理程序的工厂。

HandlerFactory.createMouseHandler();

并且方法createMouseHandler包含类似

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

如果您不想要这些选项中的任何一个,我会考虑使用方面框架(可能是 AspectJ)或用于控制反转的容器(可能是 Spring IoC)。方面允许您注释您的源代码,并在选定的位置“编织”代码。IoC 容器允许您控制对象的生命周期(例如实例化)。两者都在幕后使用字节码检测。

但是如果你想自己做instrumentation,我只能比较我个人使用的Javassist和ASM。

ASM是低级的,并且实际上在 java 字节码级别运行。你一定很熟悉它。该框架设计得非常好,手册非常好,它是一个很棒的库。一方面,替换字节码模式可能很复杂,因为它需要所谓的“有状态”转换。另一方面,您可以完全控制字节码。

Javassist更高级。您不在字节码的原始级别操作,略高一点,例如字段读/写、消息发送、构造函数。此外,它允许您使用常规 java 语法指定更改,然后由框架编译。API 有点混乱,因为该项目多年来一直在增长。有关于框架的文档,但不像 ASM 那样集中。

于 2012-04-18T09:08:20.227 回答