Java 在运行时重定向方法调用以引入某种沙箱

Java 在运行时重定向方法调用以引入某种沙箱,java,java-7,Java,Java 7,这个问题我有点棘手。希望有一颗银弹 我有一些单例(~10),它们都有一些函数(~10个)。我的函数调用是这样的(它们应该是这样的)。注意:大多数调用是异步的,不返回任何内容。只有少数是同步的 我需要将所有这些调用放在沙箱中: Sandbox.runThisInSandboxMode(new Runnable{ @Override public void run(){ SingletonClassGorrilla.getInstance().methodSwim(s

这个问题我有点棘手。希望有一颗银弹

我有一些单例(~10),它们都有一些函数(~10个)。我的函数调用是这样的(它们应该是这样的)。注意:大多数调用是异步的,不返回任何内容。只有少数是同步的

我需要将所有这些调用放在沙箱中:

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();
    }
}