关于java:Java动态代理

40次阅读

共计 2937 个字符,预计需要花费 8 分钟才能阅读完成。

1. 本人实现代理类

public interface BizDemo {void helloGirl(String name);

    void helloBoy(String name);
}


public class BizDemoImpl implements BizDemo{
    @Override
    public void helloGirl(String name) {System.out.println( name + "helloGirl in BizDemoImpl");
    }

    @Override
    public void helloBoy(String name) {System.out.println( name + "helloBoy in BizDemoImpl");
    }
}

public class BizDemoImplProxy implements  BizDemo {
    private BizDemo real;
    BizDemoImplProxy(BizDemo real) {this.real = real;}
    @Override
    public void helloGirl(String name) {System.out.println("proxy by BizDemoImplProxy");
        this.real.helloGirl(name);
    }
    @Override
    public void helloBoy(String name) {System.out.println("proxy by BizDemoImplProxy");
        this.real.helloBoy(name);
    }
}

    public static void main(String[] args) {BizDemo demo = new BizDemoImpl();
        demo.helloGirl("Lucy");
        BizDemo demoProxy = new BizDemoImplProxy(demo);
        demoProxy.helloGirl("Lucy");
   }
// 输入
LucyhelloGirl in BizDemoImpl
proxy by BizDemoImplProxy
LucyhelloGirl in BizDemoImpl

2. 用 java 动静代理生成类

    1. 首先让咱们忘掉对 BizDemoImpl 做代理,看看 java 主动生成代理类的成果
public class ProxyHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("proxy invoke." + args[0]);
        return null;
    }
}

能够看到,只有有 BizDemo 这个接口,就能够通过 java 动静代理生成一个类, 这个类领有接口 BizDemo 的所有办法,并且把所有办法调用,都透传到 ProxyHandler 的 invoke 办法中。

    public static void main(String[] args) {Class[] inf = new Class[] {BizDemo.class};
        BizDemo d =  (BizDemo) Proxy.newProxyInstance(BizDemo.class.getClassLoader(), inf, new ProxyHandler());
        d.helloGirl("javaDynamicProxy");
        d.helloBoy("javaDynamicProxy boy");
}
// 输入
proxy invoke.javaDynamicProxy
proxy invoke.javaDynamicProxy boy

只管咱们能够让 java 给咱们动静生成一个类,这个类实现了 BizDemo 接口,然而这样的类没有太多的实际意义。咱们的目标是代理 BizDemoImpl,看看咱们是怎么达到的

    1. 让代理产生实际意义,对 BizDemoImpl 做代理
      其实很简略,咱们只有把 BizDemoImpl 实例塞到 ProxyHandler 里,在 invoke 办法再调一次不就行了吗,于是咱们翻新创立一个 Handler: ProxyHandler1
public class ProxyHandler1 implements InvocationHandler {

    private BizDemo real;
    public ProxyHandler1(BizDemo real) {this.real = real;}

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("proxy invoke." + args[0]);
        if (method.getName().equals("helloBoy")) {this.real.helloBoy((String)args[0]);
        } else {this.real.helloGirl((String)args[0]);
        }
        return null;
    }
}
    public static void main(String[] args) {BizDemo demo = new BizDemoImpl();
        Class[] inf = new Class[] {BizDemo.class};
        BizDemo d =  (BizDemo) Proxy.newProxyInstance(BizDemo.class.getClassLoader(), inf, new ProxyHandler1(demo));
        d.helloGirl("javaDynamicProxy");
        d.helloBoy("javaDynamicProxy boy");
}
// 输入
proxy invoke.javaDynamicProxy
javaDynamicProxyhelloGirl in BizDemoImpl
proxy invoke.javaDynamicProxy boy
javaDynamicProxy boyhelloBoy in BizDemoImpl

能够看到,动静代理生成的类,真正的代理了 BizDemoImpl 实例 demo

单从上述例子看,用 java 动静代理,反而更简单类,要引入 InvocationHandler 和 java.lang.reflect.Proxy, 但认真想是有益处的,
第一,不论用户的 interface 有多少个办法,最终都代理收拢到 InvocationHandler 的 invoke
第二,如果我的项目有很多 interface 要代理,代理类会成倍增加,难以保护

java 动静代理类图如下,
$Proxxy0 是 java 动静生成的类,这个类继承类 Proxy 实现了 BizDemo 接口,也就是上述的 main 中的 d,对 d 的调用,先到 $Proxy0, $Proxxy0 委托给父类的 Proxy 的成员变量 InvocationHandler 实例,即 ProxyHandler1 实例; 而 ProxyHandler1 实例的 invoke 办法里最终调用了被代理的 BizDemoImpl。
总之看起来很绕,框架类的代码往往就义直观来实现通用和简洁

正文完
 0