Java 在运行时重定向方法调用以引入某种沙箱
这个问题我有点棘手。希望有一颗银弹 我有一些单例(~10),它们都有一些函数(~10个)。我的函数调用是这样的(它们应该是这样的)。注意:大多数调用是异步的,不返回任何内容。只有少数是同步的 我需要将所有这些调用放在沙箱中:Java 在运行时重定向方法调用以引入某种沙箱,java,java-7,Java,Java 7,这个问题我有点棘手。希望有一颗银弹 我有一些单例(~10),它们都有一些函数(~10个)。我的函数调用是这样的(它们应该是这样的)。注意:大多数调用是异步的,不返回任何内容。只有少数是同步的 我需要将所有这些调用放在沙箱中: Sandbox.runThisInSandboxMode(new Runnable{ @Override public void run(){ SingletonClassGorrilla.getInstance().methodSwim(s
Sandbox.runThisInSandboxMode(new Runnable{
@Override
public void run(){
SingletonClassGorrilla.getInstance().methodSwim(swimmingPool, lifeJacket, whistle);
}
});
由于调用它们的地方数量巨大,我希望在单例端可以实现sandboxMode
可能的解决方案(但不可行,因为我必须像这样包装函数的数量):
通过使用语言中的反射/注释/任何其他东西,是否可以减少所需的更改量?您可以使用带有合适的调用处理程序的调用处理程序(尽管您必须为每个单例拉出接口)。免责声明:我还没有尝试编译/运行这段代码,但它应该会给你一个大致的想法。如果您关心单例的返回值,那么您可能必须在沙盒界面中使用Callable
,而不是/除了Runnable
public class SingletonGorilla implements GorillaInterface {
private static SingletonGorilla theRealGorilla;
public static GorillaInterface getInstance() {
//In reality, you'd want to store off the Proxy as well
return Proxy.newProxyInstance(SingletonGorilla.class.getClassLoader(), GorillaInterface.class, new SandboxingHandler());
}
private static class SandboxingHandler implements InvocationHandler () {
public Object invoke(Object proxy, Method method, Object[] args) {
return Sandbox.runInSandbox( new Runnable() {
public void run () {
method.invoke(proxy, args));
}
}
}
}
我在想以下几点:
首先,您需要为每个单件设置一个接口:
接口:
package org.test.proxywrapper;
public interface IGorilla {
public void methodSwim();
}
实现类:
package org.test.proxywrapper;
public class Gorilla implements IGorilla{
public void methodSwim()
{
}
}
然后,实现一个InvocationHandler,对Gorilla方法的每次调用都会用到的代码进行分解:
package org.test.proxywrapper;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class WrapperInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
Sandbox.runThisInSandboxMode(new Runnable() {
@Override
public void run() {
Object params = new Object[0];
try {
arg1.invoke(arg0, new Object[]{});
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
});
// return something if you need to
return new Object();
}
}
此时,在应用程序/系统的中心位置,用代理包裹每个单例,并传递代理引用,而不是原始包裹对象:
package org.test.proxywrapper;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String argv[])
{
WrapperInvocationHandler wrapperInvocationHandler = new WrapperInvocationHandler();
Class<?>[] implementedTypes = new Class<?>[1];
implementedTypes[0] = IGorilla.class;
IGorilla proxy = (IGorilla) Proxy.newProxyInstance(Main.class.getClassLoader(), implementedTypes, wrapperInvocationHandler);
proxy.methodSwim();
}
}
package org.test.proxywrapper;
导入java.lang.reflect.Proxy;
公共班机{
公共静态void main(字符串argv[])
{
WrapperInvocationHandler WrapperInvocationHandler=新的WrapperInvocationHandler();
Class[]implementedTypes=新类[1];
implementedTypes[0]=IGorilla.class;
IGorilla proxy=(IGorilla)proxy.newProxyInstance(Main.class.getClassLoader(),implementedTypes,wrapperInvocationHandler);
proxy.methodSwim();
}
}
这个简单的示例按照我的预期编译和运行。
我在这里走了一些弯路,跳过了getInstance方法,等等,但我想它给出了如何实现的想法 当单例中有多个方法时,处理程序会做什么。它怎么知道该打电话给谁。调用会处理路由吗?如何调用?invoke
(Method arg1
)的第二个参数是对正在调用的反射方法的引用,您可以编写arg1.invoke(arg0,new Object[]{})
,一分钟后查看编辑过的答案。我将删除lambda,问题标记为java-7。
package org.test.proxywrapper;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class WrapperInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
Sandbox.runThisInSandboxMode(new Runnable() {
@Override
public void run() {
Object params = new Object[0];
try {
arg1.invoke(arg0, new Object[]{});
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
});
// return something if you need to
return new Object();
}
}
package org.test.proxywrapper;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String argv[])
{
WrapperInvocationHandler wrapperInvocationHandler = new WrapperInvocationHandler();
Class<?>[] implementedTypes = new Class<?>[1];
implementedTypes[0] = IGorilla.class;
IGorilla proxy = (IGorilla) Proxy.newProxyInstance(Main.class.getClassLoader(), implementedTypes, wrapperInvocationHandler);
proxy.methodSwim();
}
}