Java: 是否可以在运行时向活动对象实例添加/附加代理?

Java: Is it possible to add / attach a proxy to a live object instance during runtime?

我知道 Java 支持代理。我一直在检查 Javassist 但不确定它是否可以支持以下技巧:

public class Hello {

    public void hi() {
        System.out.println("hi");
    }
}

Hello hello = new Hello();

Hello proxyHello = createProxy(hello);
proxyHello.hi(); // method will be intercepted by a predefined proxy

是否可以这样做?

您可以使用 java.lang.reflect.Proxy 来完成这样的事情。

https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html

JDK中可用的只允许创建实现一组接口的代理,如果要创建Class的代理,则需要使用Javassist 但是为了能够做到这一点,您需要一个可以从创建代理的 class 访问的构造函数。

这里有一个实现你所需要的方法:

final Hello hello = new Hello() {
    public void hi() {
        System.out.println("Hello World");
    }
};
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(Hello.class);
MethodHandler handler = (self, m, proceed, args) -> {
    // This allows to proxy even non accessible methods, it could not be
    // needed depending on your context
    if (!m.isAccessible())
        m.setAccessible(true);
    return m.invoke(hello, args);
};
Hello proxy = (Hello)factory.create(new Class<?>[0], new Object[0], handler);
proxy.hi();

输出:

Hello World

在这个例子中:

  1. 首先我创建我的工厂
  2. 那我提供超级class
  3. 然后我定义如何处理代理上的所有方法调用(这里我将所有内容委托给我的活动对象)
  4. 最后我创建了我的代理(这里我使用默认构造函数来创建代理)。

更多详情here

假设您有一个带有一个 String 参数的构造函数,您需要将最后一行修改为下一行:

Hello proxy = (Hello)factory.create(
    new Class<?>[]{String.class}, new Object[]{"bar"}, handler
);

在这里,我使用一个 String 类型的参数调用构造函数,并提供 bar 作为值。