Java 为什么JDK动态代理只与接口一起工作?
JDK代理类只接受工厂方法newProxyInstance()中的接口 是否有解决方法或替代实现? 如果我必须将方法提取到接口以使它们能够与代理一起使用,那么用例是有限的。我想包装它们,以便在运行时应用基于注释的操作Java 为什么JDK动态代理只与接口一起工作?,java,dynamic-proxy,Java,Dynamic Proxy,JDK代理类只接受工厂方法newProxyInstance()中的接口 是否有解决方法或替代实现? 如果我必须将方法提取到接口以使它们能够与代理一起使用,那么用例是有限的。我想包装它们,以便在运行时应用基于注释的操作 public static <T> T getProxy(T obj) { InvocationHandler ih = new InjectProxy( obj ); ClassLoader classLoader = InjectProxy.class.
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 );
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
publicstatict getProxy(T obj){
InvocationHandler ih=新的InjectProxy(obj);
ClassLoader ClassLoader=InjectProxy.class.getClassLoader();
return(T)Proxy.newProxyInstance(classLoader,obj.getClass().getInterfaces(),ih);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
是否有解决办法
嗯。有。从现有类中提取接口
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());
}
如果你需要一些“通用”的东西,你应该像@Peter Lawrey allready所说的那样使用AOP
或替代实现
你可以用
关于cglib替代品的类似帖子:您可以像这样使用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));
}
}
import java.lang.reflect.Array;
导入java.lang.reflect.Method;
导入java.lang.reflect.Modifier;
导入net.sf.cglib.proxy.Enhancer;
导入net.sf.cglib.proxy.MethodInterceptor;
导入net.sf.cglib.proxy.MethodProxy;
公共类抽象工厂{
@抑制警告(“未选中”)
公共静态A createDefaultImplementation(类abstractClass){
增强子增强子=新增强子();
增强子.setSuperclass(abstractClass);
setCallback(新的MethodInterceptor(){
公共对象拦截(对象代理、方法、对象[]参数、方法代理)抛出可丢弃的{
如果(!Modifier.isAbstract(method.getModifiers())){
returnmethodproxy.invokeSuper(proxy,args);
}否则{
Class type=method.getReturnType();
if(type.isPrimitive()&&!void.class.equals(type)){
返回Array.get(Array.newInstance(type,1),0);
}否则{
返回null;
}
}
}
});
return(A)enhancer.create();
}
@抑制警告(“未选中”)
公共静态createDefaultImplementation(字符串className)抛出ClassNotFoundException{
返回(A)createDefaultImplementation(Class.forName(className));
}
}
例如,此示例允许您使用默认实现方法构建抽象类。但是您可以根据需要更改增强器。原则上,您可以使用ASM之类的字节码库自己创建基于类的代理。@Krik,有些单元测试模拟库可以这样做。您需要创建一个派生类来重写所需的方法。(自动或手动)您是否考虑过Aspect-J,它被设计用来做这类事情?@Peter Lawrey我希望有一个使用核心java的解决方案。您可以为派生类创建代码,并在运行时编译/加载它。您可以使用编译器API来实现这一点。谢谢,但正如我已经提到的:“如果我必须将方法提取到接口以使它们能够与代理一起使用,那么用例是有限的”@stacker,似乎您不需要一些util,只需解决具体问题。。为此,我更新了我的帖子。