动态代理:jdk之ProxyInvocationHandler-万能模板的构建

对于代理模式,分为静态代理与动态代理,虽然静态代理有诸多好处,但是有一点:代码量翻倍就不好了,因此当我们需要代理大量对象的时候,静态代理显然不能再使用了,为了适应这种情况,衍生出动态代理。

动态代理实现方式又有:1.jdk-Proxy与InvocationHandler 2.cglib 3.javasist等等。

本节我们以jdk中的动态代理从一步步使用到推到成一个万能模板,OK let's start!

ps:如果大家不想知道太多我怎么一步步演化过去,只想用我写的最终的万能模板动态代理代码的话,ok,拉到最下面!

====

假如现在有一个人想租房东(Host)的房子,但是房东他找不到,他只能通过中介来租房子,OK以这个例子来描绘动态代理。

====

ps:我们实现动态代理,被代理的对象必须有接口,这个想必有点设计模式的人都有这种思想,OK,提一下!

房东租房子的接口:

public interface Rent {
    void rent();
}

具体的房东:

public class Host implements Rent {
    public void rent() {
        System.out.println("房东出租房子!");
    }
}

//初步的动态代理类:

public class ProxyInvocationHandler implements InvocationHandler {
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }
    
    public Object getProxyClass(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(rent,args);
    }
}

调用:

 public static void main(String[] args) {
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();//动态代理类
        proxyInvocationHandler.setObj(new Host());//需要代理的对象
        Rent proxyClass = (Rent) proxyInvocationHandler.getProxyClass();//创建并获取代理对象
        proxyClass.rent();//代理对象方法调用
    }

上方的这些代码,看起来是没什么问题哈,动态代理的功能也确实实现了,但是呢?有两个问题:

1.动态代理的对象写死为Rent,这个动态代理对象无法代理除Rent以外的对象

2.代理对象一般都需要增强一些功能的添加,这里如果增加的话,直接在ProxyInvocationHandler增加,这岂不是违反了开闭原则,根本无法封装

为了解决上面的两个问题,OK我们来逐个分析:

1.我们可以将Rent对象变为Object就解决了,OK这个没问题

2.方法不能写死,那么怎么办呢?使用模板方法的思想,我们将方法的实现抽离出来,将方法的动作保留,同时考虑到可能没有这个动作,因此:有这个动作,我们就做这个动作,如果没有这个动作,那么就不做这个动作(很简单判断对象是否为null就好啦)。

OK,分析的很合理,let's write code:

public class ProxyInvocationHandler implements InvocationHandler {
    //设置代理类
    private Object obj;
    private preFunc pre;
    private endFunc end;

    public void setObj(Object _obj) {
        this.obj = _obj;
    }

    public void setObj(Object _obj, preFunc pre, endFunc end) {
        this.obj = _obj;
        this.pre = pre;
        this.end = end;
    }

    //获取代理对象
    public Object getProxyClass() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }

    //处理代理示例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(pre!=null)pre.doSomething();
        //动态代理的本质就是使用反射
        Object result = method.invoke(obj, args);
        if(end!=null)end.doSomething();
        return result;
    }

    public interface preFunc {
        void doSomething();
    }

    public interface endFunc {
        void doSomething();
    }
}

如何调用处理代码呢?

  public static void main(String[] args) {
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();//动态代理类
        proxyInvocationHandler.setObj(new Host(), new ProxyInvocationHandler.preFunc() {
            @Override
            public void doSomething() {
                System.out.println("中介者dosomethingBefore");
            }
        }, new ProxyInvocationHandler.endFunc() {
            @Override
            public void doSomething() {
                System.out.println("中介者dosomethingAfter");
            }
        });//需要代理的对象
        Rent proxyClass = (Rent) proxyInvocationHandler.getProxyClass();//创建并获取代理对象
        proxyClass.rent();//代理对象方法调用
    }

perfect,搞定!

每天努力一点点,继续加油哦~~

原文地址:https://www.cnblogs.com/ningxinjie/p/13358535.html