Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么JDK动态代理只与接口一起工作?_Java_Dynamic Proxy - Fatal编程技术网

Java 为什么JDK动态代理只与接口一起工作?

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.

JDK代理类只接受工厂方法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 );
                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
}
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,只需解决具体问题。。为此,我更新了我的帖子。