java - 如何 "proxy"Java中的一个方法

标签 java reflection

首先,我不确定如何最好地表达我的解决方案,所以如果我有时似乎在喋喋不休,请考虑一下。

我希望在不触及物理代码的情况下修改库中的一个接口(interface),

public interface ProxiedPlayer {
    // .. other code
    public void setPermission(String permission, boolean state);
}

我已经编写了一个第三方库来处理权限,并且必须挂接到我的 API 来编辑权限可能是一些开发人员不想采取的步骤。所以我问,当 setPermission 被调用时,是否有可能让它调用我调用我的库中的适当方法来处理权限设置同时忽略预编程代码或不是吗?

这是完整的 interface我正在尝试代理。

我已经查看了 Java 代理类 ,但看起来您首先需要一个您尝试代理的对象的实例。 鉴于我可以随时调用该方法不相信这是我的解决方案但很乐意接受纠正。

我无法控制实现 ProxiedPlayer 接口(interface)的类的实例化。

编辑:无知的我,我可以订阅几个事件,在那里可以获得播放器的实例,这是尝试代理该方法的合适位置吗?当玩家加入服务器并且可以获取玩家的实例时,将触发这些事件之一。

是否需要为 ProxiedPlayer 接口(interface)的每个实例调用代理代码,或者是否可以以更简单的方式简单地代理方法的每次调用?

我的库是一个插件,在其他所有必需的东西都加载完成后加载。

编辑#2:

import net.md_5.bungee.api.connection.ProxiedPlayer;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class InvocationProxy implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        ProxiedPlayer player = (ProxiedPlayer) proxy;
        if(method.getName().equals("setPermission")) {
            // Call my code here?
        }
        return method.invoke(player, args);
    }
}

按照我上面的方法行事,还是我完全找错了树?

最佳答案

如果您不想接触原始来源,那么您只能通过使用 Java 代理来解决这个问题,该代理重新定义任何实现 ProxiedPlayer 接口(interface)的类,以便在调用实际之前强制执行安全检查方法。已经提到 AspectJ 和加载时编织代理作为一个可能的解决方案,但您也可以使用我的库实现纯 Java 解决方案 Byte Buddy :

public class InterceptionAgent {
  public static void premain(String arguments, 
                             Instrumentation instrumentation) {
    new AgentBuilder.Default()
      .rebase(isSubtypeOf(ProxiedPlayer.class))
      .transform(new AgentBuilder.Transformer() {
        @Override
        public DynamicType.Builder transform(DynamicType.Builder builder) {
          return builder.method(named("setPermission"))
                        .intercept(MethodDelegation.to(MyInterceptor.class)
                      .andThen(SuperMethodInvocation.INSTANCE));
        }
      }).installOn(instrumentation);
  }
}

使用此代理,您或多或少地指定要重新定义作为 ProxiedPlayer 子类型的任何类以重新定义名为 setPermisson 的(任何)方法,以便调用 MyInterceptor(这将是您的代码)并随后调用原始实现。

请注意,建议的实现假定所有实现 ProxiedPlayer 的类都实现了此接口(interface)的方法,并且只有一个方法具有此签名。这可能太简单了,但它显示了前进的方向。

关于java - 如何 "proxy"Java中的一个方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28265626/

相关文章:

c# - 用常量替换表达式中的参数

java - 哪些工具可用于将测试数据填充到 mongodb

java - Android sqlite insert 没有插入

java - Apache POI 使用 HSSF 比 XSSF 快得多 - 下一步是什么?

java - 通过反射获取getter的fieldname

java - 如何使用 Java 反射调用父类(super class)方法

java - 无法获取父类(super class)中定义的上下文

Java mailto 到 MIME

java - 如何防止通过反射访问?

Java:从 JAR 文件中的类文件中获取方法 stub 的简单方法?反射?