gpt4 book ai didi

java - 我怎样才能拦截从 Java 到 Groovy 的调用——或者很容易地模拟它

转载 作者:行者123 更新时间:2023-11-29 09:14:44 27 4
gpt4 key购买 nike

我希望使用 groovy 的 invokeMethod 来执行此操作,但事实证明,当您从 Java 调用 Groovy 时,不会调用 invokeMethod,否则它会完美地工作。

我有一个案例,我将一个 Groovy 类提交给一个 Java 类(我无法编辑)。 Groovy 类被注释,Java 类扫描注释并将注释的方法保存为其事件的监听器。

当事件发出时,我想从事件对象中获取一些信息,使用它来检索数据并将该数据注入(inject)脚本中的事件处理程序(通过该方法中的注释变量)。

我可以控制的事情——我实例化脚本,为它们设置一个基类,然后将它们传递给其他系统进行注册。脚本将由其他人编写——我可以控制脚本的设计,但我的目标是简单。

我可能会创建一个适配器类,但这似乎非常困难和脆弱,因为我必须手动注册所有这些方法,而不是像现在这样使用注释——有很多不同的事件需要监听.

我想知道是否有我没有考虑的绝妙技巧。我对 groovy 元编程还是很陌生。也许有一种方法可以自动创建适配器类,或者当我编译脚本时,用转发方法替换方法,在调用它们的真实方法之前转发到我的代码——任何可能的方法?

请求的源代码:

源代码——让我们看看,这个过程分布在几个类中......

这就是我使用 ScriptBase 设置 Groovy 类加载器的方式

cconfig.setScriptBaseClass("tv.kress.bill.minecraft.ezplugin.ScriptBase");
GroovyClassLoader gcl = new GroovyClassLoader(getClass().getClassLoader(), cconfig);

然后我将它传递给 Groovy 脚本引擎(我在这里遗漏了一些东西)

gse = new GroovyScriptEngine(cpString, gcl);

然后我实例化脚本

scriptClass = gse.loadScriptByName(file.getAbsolutePath());
instance = (GroovyObject) scriptClass.newInstance();

然后,如果它是一个“监听器”,它是“固定”java 库用来识别它应该扫描注释的 java 类的标记接口(interface),我将它传递给那个类,以便可以注册任何带注释的方法(沿线的某个地方“实例”变成了“脚本”,虽然是同一个对象:

 if (script instanceof Listener)
pm.registerEvents((Listener) script, this);

脚本本身有趣的部分如下所示:

@EventHandler
public void userEvent(UserInteractEvent event) {

我想添加的是在 userEvent 中添加一个带注释的局部变量的能力,如下所示:

    @Persist int persistedPerUserData // Or @PersistPerUser? or @Persist(User=true)?

这样就在调用 userEvent 之前,我可以拦截它。我将从 UserInteractionEvent 中获取用户名,将其与脚本、变量和方法名称结合起来,以获得一个独特的签名,如“MyScript:UserEvent:Bill:persistedPerUserData”,并使用它来检索一个我可以放入 persistedPerUserData 中的整数。

稍后在方法返回后从 persistedPerUserData 中获取值并将其存储回“MyScript:UserEvent:Bill:persistedPerUserData”(目前是一个散列,但我希望最终将其变成一个数据库)。

通过这种方式,脚本永远不必考虑它正在处理不同的用户这一事实,它只需要有一组变量并且所有的持久性都可以正常工作。

还有其他事件也适用,但我相信它们都扩展了同一个事件,并且根事件具有“用户”字段。

编辑:就像不要尝试的另一件事一样,我尝试像这样使用 ProxyMetaClass/拦截器:

// Attempt (and fail) to intercept calls to an instance of clazz
class Slicer {
public static Object slice(Class clazz) {
Object instance;
def proxy = ProxyMetaClass.getInstance(clazz);
proxy.interceptor = new MyInterceptor();
proxy.use {
instance = clazz.newInstance();
}
return instance;
}
}

结果相同,来自 groovy 类的每个调用都被很好地检测,但没有拦截来自 Java 的调用。回到绘图板。我想这就是 Aspects 使用字节码操作的原因。

最佳答案

我真的还没有找到答案,但我想出了一些我认为可行的东西——我想没有人提到它,因为它太明显了,但我仍然在“用 Java 思考”更多比常规。

好的,我希望脚本实现看起来像这样:

@EventHandler
public void userEvent(UserInteractEvent event) {
@Persist int persisteData
// At this point persistedData contains data different depending on which user was passed in
...

我认为如果我使用闭包我认为我可以做一些关闭的事情:

@EventHandler
public void userEvent(UserInteractEvent event) {
persistScope(event.user) {
@Persist int persistedPerUserData // Or @PersistPerUser? or @Persist(User=true)?
...

这样,在 persistScope 中,我可以扫描闭包中的 @Persist 注释并执行我的操作。这可能无法正常工作,因为直到闭包开始才创建该 int,但我认为只要我从 groovy 调用到 groovy,我就可以使用我在问题中提到的方法来修复它。要么,要么我将“它”变成一个包含持久化用户数据的散列。

它有点笨拙,但我认为它会起作用,而且我喜欢它更明确的事实(事实上,之前我只是假设传入的“事件”有一个 .getUser() 方法,现在我可以将持久性范围限定为我想要的任何东西)。

我会尝试实现它并给它几天时间,看看是否有人在接受它之前就我提出的原始问题提出了答案。

编辑:我对这个解决方案不满意。由于变量是在该范围内声明的,因此我无法使用 @Persist 注释,因此我传入了一个哈希值,该模块可以将其用作数据容器,然后在闭包返回后将其持久化。

仍在寻找更好的答案...

关于java - 我怎样才能拦截从 Java 到 Groovy 的调用——或者很容易地模拟它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10205496/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com