zoukankan      html  css  js  c++  java
  • 动态代理: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,搞定!

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

  • 相关阅读:
    路飞学城-Python开发集训-第3章
    路飞学城-Python开发集训-第2章
    路飞学城-Python开发集训-第1章
    Python:Day55 ORM多表操作
    Python:Day54 ORM
    Django的auth【认证】模块简介
    importlib的用法
    Django中的forms一些小点
    利用xlrd模块读取excel利用json模块生成相应的json文件的脚本
    json的内容回顾
  • 原文地址:https://www.cnblogs.com/ningxinjie/p/13358535.html
Copyright © 2011-2022 走看看