Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does JDK dynamic Proxy only work with Interfaces?

The JDK Proxy class only accepts interfaces in the factory method newProxyInstance().

Is there a workaround available, or alternative implementations? The use cases are limited if I have to extract methods to an interface in order to enable them for use with a proxy. I would like to wrap them to apply annotation based actions during runtime.

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 );
                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
}
like image 205
stacker Avatar asked Dec 10 '10 16:12

stacker


1 Answers

You can use cglib like this:

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));
    }
}

This for example lets you build abstract classes with a default implementation method. But you can change the enhancer to what ever you want.

like image 145
ahvargas Avatar answered Oct 21 '22 02:10

ahvargas