美文网首页
最简单的动态代理例子

最简单的动态代理例子

作者: YocnZhao | 来源:发表于2019-02-13 13:43 被阅读0次

    一个最简单的动态代理的例子

    其实对于动态代理技术,大家大可不必被它的名字吓到,自己写一个就知道了。我第一次听这个东西的时候去网上看介绍,被网上的例子跟拟人的解释搞的迷迷糊糊的。像班长代理学生们向班主任交班费的例子,真的是一脸懵逼。
    当然虽然我吐槽了,但是我自知自己也讲不好,所以大家不理解的回去写个最简单demo就知道了,然后慢慢扩展,想想在项目中有什么地方可以用到,不用跟逻辑太切合,能应用起来就好了,万万不要被网上的例子搞的迷糊了就觉着这个好难就放弃了,其实就那么回事儿。

    其实我理解的动态代理,就是我有一个接口扔给你,你给我返回一个这个接口的实例,就这么简单。

    但是实际上我们不能扔一个接口,像下面的例子中我写了一个class 实现了interface,然后把这个类的实例给create,然后create了一个代理对象出来。那我们可能会想,我既然已经有了一个类的对象为什么还要让你给我代理一个出来呢?这不是脱裤子放屁-多此一举吗。是的,下面的例子只是一个探索,实际上还是需要看使用场景的,我们先看例子。

    动态代理首先得有两个最重要的东西

    1. 有一个接口
    2. 重写Proxy.newProxyInstance中的InvocationHandler
    public class SimpleDynamicProxy {
        public void test() {
            SimpleInterface simpleInterface = createSimple(new SimpleClass());
            simpleInterface.doThing1();
            simpleInterface.doThing2();
        }
    
        interface SimpleInterface {
            void doThing1();
    
            void doThing2();
        }
    
        public class SimpleClass implements SimpleInterface {
    
            @Override
            public void doThing1() {
                LogUtil.Companion.d("doThing1");
            }
    
            @Override
            public void doThing2() {
                LogUtil.Companion.d("doThing2");
            }
        }
    
        private SimpleInterface createSimple(SimpleInterface object) {
            /*最简单的例子,传进来一个继承了SimpleInterface的class的实例,我们拿到*/
            return (SimpleInterface) Proxy.newProxyInstance(
                    //这里其实可以用谁的classLoader都行,只要是AppClassLoader就可以,可以用new SimpleClass().getClass().getClassLoader()代替
                    object.getClass().getClassLoader(),
                    //获取到需要代理的接口,这里可以看出来必须要有接口,没有实现接口的class是不可以动态代理的,因为没有实现接口
                    object.getClass().getInterfaces(),
                    //重写InvocationHandler,这是动态代理最重要的点,我们使用动态代理其实就是为了在下面做事情
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            LogUtil.Companion.d("simple dynamic proxy");
                            // 千万不可以用method.invoke(proxy, args),自己调用自己会造成递归调用,无法退出 !!!!!!!
                            method.invoke(object, args);
                            return null;
                        }
                    });
        }
    }
    

    上面是最简单的动态代理的例子。我给一个集成了接口的类的对象,会返回给我一个有全部功能的代理类。
    最重要的是重写InvocationHandler,我们能做的大部分事情都在重写的invoke里面,我们能拿到调用的所有的信息,包括调用的对象、方法、参数,那其实我们想在这里做什么都可以了。最简单的加统计,加曝光,或者调用某几个通用的方法,还可以判断调用的方法不同调用某个方法。

    下面这个例子是加了多态的更通用的,实现了接口的多个子类调用的时候返回不同的类。

    public class SimpleDynamicProxy {
        public void test() {
            SimpleInterface simpleInterface = createSimple(new SimpleClass1());
            simpleInterface.doThing1();
            SimpleInterface generalInterface1 = createT(new SimpleClass1());
            generalInterface1.doThing1();
            SimpleInterface generalInterface2 = createT(new SimpleClass2());
            generalInterface2.doThing1();
            LogUtil.Companion.d("doStringThing->" + generalInterface2.doStringThing());
            LogUtil.Companion.d("doIntThing->" + generalInterface2.doIntThing());
        }
    
        interface SimpleInterface {
            void doThing1();
    
            String doStringThing();
    
            int doIntThing();
        }
    
        public class SimpleClass1 implements SimpleInterface {
    
            @Override
            public void doThing1() {
                LogUtil.Companion.d("SimpleClass1 doThing1");
            }
    
            @Override
            public String doStringThing() {
                return "SimpleClass1 doThing2";
            }
    
            @Override
            public int doIntThing() {
                return 1001;
            }
        }
    
        public class SimpleClass2 implements SimpleInterface {
    
            @Override
            public void doThing1() {
                LogUtil.Companion.d("SimpleClass2 doThing1");
            }
    
            @Override
            public String doStringThing() {
                return "SimpleClass1 doThing2";
            }
    
            @Override
            public int doIntThing() {
                return 1221;
            }
        }
    
        private SimpleInterface createSimple(SimpleInterface object) {
            /*最简单的例子,传进来一个继承了SimpleInterface的class的实例,我们拿到*/
            return (SimpleInterface) Proxy.newProxyInstance(
                    //这里其实可以用谁的classLoader都行,只要是AppClassLoader就可以,可以用new SimpleClass().getClass().getClassLoader()代替
                    object.getClass().getClassLoader(),
                    //获取到需要代理的接口,这里可以看出来必须要有接口,没有实现接口的class是不可以动态代理的,因为没有实现接口
                    object.getClass().getInterfaces(),
                    //重写InvocationHandler,这是动态代理最重要的点,我们使用动态代理其实就是为了在下面做事情
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            LogUtil.Companion.d("simple dynamic proxy");
                            // 千万不可以用method.invoke(proxy, args),自己调用自己会造成递归调用,无法退出 !!!!!!!
                            method.invoke(object, args);
                            return null;
                        }
                    });
        }
    
        private <T> T createT(SimpleInterface object) {
            /*更加通用的实现方式,假如我有多个实现了SimpleInterface的class,那可以实现传过来什么代理成什么的实现,可以看上面的调用。
            * SimpleClass1和SimpleClass2传过来什么代理出来什么。*/
            Object o = Proxy.newProxyInstance(
                    object.getClass().getClassLoader(),
                    object.getClass().getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            LogUtil.Companion.d("dynamic dynamic proxy");
                            //返回值表示方法的返回值,String或者int或者对象或者其他...
                            return method.invoke(object, args);
                        }
                    });
            return (T) o;
        }
    }
    

    上面就是最简单的一个动态代理的例子,demo先领会,可以先往项目中小功能加一加,或者搞个ABTest加一下,领会功能。差不多了之后设计功能的时候就可以扔进去用了~~

    相关文章

      网友评论

          本文标题:最简单的动态代理例子

          本文链接:https://www.haomeiwen.com/subject/sabreqtx.html