Why does JDK dynamic Proxy only work with Interfaces?
The JDK Proxy class only accepts interfaces in the开发者_如何学Python 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 );
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
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.
Is there a workaround available..?
Yeah. There is. Extract interface from existing classes.
upd
If you need it for some specific classes, you can write smt like
//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());
}
If you need some "universal" stuff you should use AOP as @Peter Lawrey allready said.
or alternative implementations
You can use cglib.
Similar posts on alternatives to cglib : Are there alternatives to cglib?
精彩评论