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

时间:2016-04-23 14:24:04

标签: java reflection proxy javassist

我知道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

是否可以做类似的事情?

2 个答案:

答案 0 :(得分:1)

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

以下是实现所需内容的方法:

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. 然后我提供超级
  3. 然后我定义如何处理代理上的所有方法调用(这里我将所有内容委托给我的实时对象)
  4. 最后我创建了我的代理(这里我使用默认构造函数来创建代理)。
  5. 更多详情here

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

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

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

答案 1 :(得分:0)

您可以使用java.lang.reflect.Proxy来完成此类操作。

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