首先,我不确定如何最好地表达我的解决方案,所以如果我有时看起来在胡言乱语,那么请考虑这一点。
我希望在不接触物理代码的情况下修改库中的一个接口,
public interface ProxiedPlayer {
// .. other code
public void setPermission(String permission, boolean state);
}
Run Code Online (Sandbox Code Playgroud)
我已经编写了一个第三方库来处理权限,并且必须连接到我的 API 来编辑权限可能是一些开发人员不想采取的步骤。所以我问,当setPermission调用时是否可以让它调用我的库中的适当方法来处理权限设置,同时忽略预编程的代码?
这是我尝试代理的完整界面。
我已经研究过 Java Proxy 类,但似乎您首先需要尝试代理的对象的实例。鉴于可以随时调用该方法,我不相信这是我的解决方案,但很乐意纠正。
我无法控制实现 ProxiedPlayer 接口的类的实例化。
编辑:无知的我,我可以订阅几个可以获取播放器实例的事件,这是否是尝试代理该方法的适当位置?当玩家加入服务器并且可以获取玩家的实例时,会触发其中一个事件。
是否需要为 ProxiedPlayer 接口的每个实例调用代理代码,或者是否可以以更简单的方式简单地代理该方法的每个调用?
我的库是一个在其他必需的内容完成加载后加载的插件。
编辑#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);
}
}
Run Code Online (Sandbox Code Playgroud)
与我上面的内容类似的东西会起作用吗?还是我完全找错了树?
如果您不想触及原始源代码,那么您只能通过使用 Java 代理来解决此问题,该代理重新定义实现该ProxiedPlayer接口的任何类,以在调用实际方法之前强制执行安全检查。已经提到 AspectJ 与加载时编织代理作为可能的解决方案,但您也可以使用我的库Byte Buddy实现纯 Java 解决方案:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
使用此代理,您或多或少指定要重新定义作为 的子类型的任何类,ProxiedPlayer以重新定义指定的(任何)方法,setPermisson以便调用 a MyInterceptor(这将是您的代码)并随后调用原始实现。
请注意,建议的实现假设所有实现ProxiedPlayer该接口的类都实现了该接口的方法,并且该签名只有一个方法。这可能太简单了,但它表明了前进的方向。
| 归档时间: |
|
| 查看次数: |
4791 次 |
| 最近记录: |