为什么JDK动态代理仅适用于接口?

时间:2010-12-10 16:40:43

标签: java dynamic-proxy

JDK Proxy类仅接受工厂方法newProxyInstance()中的接口。

是否有可用的解决方法或替代实施? 如果我必须将方法提取到接口以便使它们与代理一起使用,则用例是有限的。我想将它们包装起来,以便在运行时应用基于注释的操作。

public static <T> T getProxy(T obj) {
   InvocationHandler ih = new InjectProxy( obj );
   ClassLoader classLoader = InjectProxy.class.getClassLoader();
   return (T) Proxy.newProxyInstance( classLoader, obj.getClass().getInterfaces(), ih );
                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
}

3 个答案:

答案 0 :(得分:16)

您可以像这样使用cglib:

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;


public class AbstractFactory {

    @SuppressWarnings("unchecked")
    public static <A> A createDefaultImplementation(Class<A> abstractClass) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(abstractClass);
        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                if (!Modifier.isAbstract(method.getModifiers())) {
                    return methodProxy.invokeSuper(proxy, args);
                } else {
                    Class type = method.getReturnType();
                    if (type.isPrimitive() && !void.class.equals(type)) {
                        return Array.get(Array.newInstance(type, 1), 0);
                    } else {
                        return null;
                    }
                }
            }
        });
        return (A) enhancer.create();
    }

    @SuppressWarnings("unchecked")
    public static <A> A createDefaultImplementation(String className) throws ClassNotFoundException{
        return (A) createDefaultImplementation(Class.forName(className));
    }
}

例如,这允许您使用默认实现方法构建抽象类。但您可以将增强器更改为您想要的任何内容。

答案 1 :(得分:5)

  

是否有可用的解决方法..?

呀。有。从现有类中提取接口。

<强> UPD

如果您需要某些特定类,可以编写类似

的smt
//interface that already exists
public interface IDomain {
    String foo();
}
//your class
public class Domain implements IDomain{
    public String foo(){
        return "domain foo";
    }
//method that doesn't placed in IDomain
    public String bar(){
        return "domain bar";   
    }
}
//So you need create new interface with bar()
//it can extend IDomain 
public interface ExtendedIDomain extends IDomain {
    public String bar();
}
//than your wrapper factory will be like this
public class Proxifier {
    public static  ExtendedIDomain getProxy(Domain obj) {
       InvocationHandler ih = new InjectProxy( obj );
       ClassLoader classLoader = InjectProxy.class.getClassLoader();
       return (ExtendedIDomain) Proxy.newProxyInstance( classLoader, new Class[]{ExtendedIDomain.class}, ih );
    }

    static class InjectProxy implements InvocationHandler {
        private final Domain domain;
        private InjectProxy(Domain domain){
            this.domain = domain;
        }

        public String invoke(Object proxy, Method method, Object[] args) throws Throwable{
            for(Method m : domain.getClass().getMethods()){
                //TODO: check signature(name, args etc) or implement some logic with annotations
                if(m.getName().equals(method.getName())){
                    return "wrapped " + m.invoke(domain, args);
                }
            }
            throw new IllegalArgumentException();
        }
    }
}
//test
    public static void main(String[] args) {
        ExtendedIDomain d = Proxifier.getProxy(new Domain());
        System.out.println(d.foo());
        System.out.println(d.bar());
    }

如果你需要一些“普遍”的东西,你应该使用AOP作为@Peter Lawrey已经说过了。

答案 2 :(得分:2)

  

或替代实施

您可以使用cglib

关于cglib替代品的类似帖子:Are there alternatives to cglib?