Java动态代理

1. 自己实现代理类

Java动态代理_第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。
总之看起来很绕,框架类的代码往往牺牲直观来实现通用和简洁

Java动态代理_第2张图片

你可能感兴趣的:(java动态代理)