java.lang.reflect.Proxy的替代方法,用于创建抽象类(而不是接口)的代理

时间:2010-07-20 15:31:01

标签: java dynamic-proxy

根据the documentation

  

[java.lang.reflect.] Proxy提供静态方法   创建动态代理类和   实例,它也是   所有动态代理的超类   这些方法创建的类。

newProxyMethod method(负责生成动态代理)具有以下签名:

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
                             throws IllegalArgumentException

不幸的是,这会阻止人们生成扩展特定抽象类的动态代理(而不是实现特定接口)。这是有道理的,因为java.lang.reflect.Proxy是“所有动态代理的超类”,从而阻止了另一个类成为超类。

因此,是否有java.lang.reflect.Proxy的替代方法可以生成从特定抽象类继承的动态代理,将所有调用重定向到 abstract 方法调用处理程序?

例如,假设我有一个抽象类Dog

public abstract class Dog {

    public void bark() {
        System.out.println("Woof!");
    }

    public abstract void fetch();

}

是否有允许我执行以下操作的课程?

Dog dog = SomeOtherProxy.newProxyInstance(classLoader, Dog.class, h);

dog.fetch(); // Will be handled by the invocation handler
dog.bark();  // Will NOT be handled by the invocation handler

2 个答案:

答案 0 :(得分:106)

可以使用Javassist(请参阅ProxyFactory)或CGLIB来完成。

Adam使用Javassist的例子:

我(Adam Paynter)使用Javassist编写了这段代码:

ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(Dog.class);
factory.setFilter(
    new MethodFilter() {
        @Override
        public boolean isHandled(Method method) {
            return Modifier.isAbstract(method.getModifiers());
        }
    }
);

MethodHandler handler = new MethodHandler() {
    @Override
    public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
        System.out.println("Handling " + thisMethod + " via the method handler");
        return null;
    }
};

Dog dog = (Dog) factory.create(new Class<?>[0], new Object[0], handler);
dog.bark();
dog.fetch();

产生此输出:

Woof!
Handling public abstract void mock.Dog.fetch() via the method handler

答案 1 :(得分:-5)

在这种情况下你可以做的是拥有一个代理处理程序,它将调用重定向到抽象类的现有方法。

你当然必须编写它,但它很简单。要创建代理,您必须给他一个InvocationHandler。然后,您只需要在调用处理程序的invoke(..)方法中检查方法类型。但要注意:您必须针对与处理程序关联的基础对象检查方法类型,而不是针对抽象类的声明类型。

如果我以你的狗类为例,你的调用处理程序的调用方法可能看起来像这样(有一个现有的关联狗子类叫做......好...... dog)< / p>

public void invoke(Object proxy, Method method, Object[] args) {
    if(!Modifier.isAbstract(method.getModifiers())) {
        method.invoke(dog, args); // with the correct exception handling
    } else {
        // what can we do with abstract methods ?
    }
}

但是,有些东西让我感到疑惑:我已经谈到了一个dog对象。但是,由于Dog类是抽象的,因此您无法创建实例,因此您拥有现有的子类。此外,正如对代理源代码的严格检查所揭示的那样,您可能会发现(在Proxy.java:362)无法为不代表接口的Class对象创建代理。)

所以,除了现实之外,你想做的事情是完全可能的。

相关问题