【问题标题】:Java: Is it possible to add / attach a proxy to a live object instance during runtime?Java:是否可以在运行时将代理添加/附加到活动对象实例?
【发布时间】:2016-04-23 14:24:03
【问题描述】:

我知道 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 reflection proxy javassist


    【解决方案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. 最后我创建了我的代理(这里我使用默认构造函数来创建代理)。

    更多详情here

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

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

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

    【讨论】:

    • 好尼古拉斯!但这仅适用于默认构造函数的简单情况,换句话说,如果我的类仅采用零参数构造函数。如果我通过不同的构造函数创建了我的对象,我会遇到麻烦!
    • 不,你只需要修改工厂的create方法的参数
    • @PikaSucar 我更新了我的答案给你一个具体的例子
    • 这违反了我的要求。当我给你一个实例时,你无法知道它是用哪个构造函数创建的,同意吗?
    • @PikaSucar 也许可以,但实际上我们并不关心,因为我们将每个方法调用委托给您的活动对象,我们只需要能够创建代理即可
    【解决方案2】:

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

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

    【讨论】:

    • 不,你不能,我的朋友
    • 你能让Hello实现一个接口吗?如果不是,那么您是对的,Proxy 将不适合您。
    猜你喜欢
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多