为什么JDK动态代理仅适用于接口?
JDK代理类仅接受工厂方法newProxyInstance()中的接口。
是否有可用的解决方法或替代实施? 如果我必须将方法提取到接口以便使它们与代理一起使用,则用例是有限的。 我想将它们包装起来,以便在运行时应用基于注释的操作。
public static T getProxy(T obj) { InvocationHandler ih = new InjectProxy( obj ); ClassLoader classLoader = InjectProxy.class.getClassLoader(); return (T) Proxy.newProxyInstance( classLoader, obj.getClass().getInterfaces(), ih ); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ }
您可以像这样使用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 createDefaultImplementation(Class 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 createDefaultImplementation(String className) throws ClassNotFoundException{ return (A) createDefaultImplementation(Class.forName(className)); } }
例如,这允许您使用默认实现方法构建抽象类。 但是您可以将增强器更改为您想要的任何内容。
有可用的解决方法..?
是啊。 有。 从现有类中提取接口。
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已经说过了。
或替代实施
你可以使用cglib 。
关于cglib替代品的类似post: 有没有cglib的替代品?