美文网首页
动态代理

动态代理

作者: 茶酒qqq | 来源:发表于2020-01-20 20:56 被阅读0次

    动态代理

    • 特点:字节码随用随创建,随用随加载
    • 作用:不修改源码的基础上对方法增强(和装饰器什么关系呢?)
    • 分类:
      • 基于接口的动态代理
      • 基于子类的动态代理

    基于接口的动态代理

    • 涉及的类:Proxy
    • 提供者:JDK官方
    • 如何创建代理对象:
      • 使用Proxy类中的newProxyInstance方法
    • 创建代理对象的要求:
      • 被代理类最少实现一个接口,如果没有则不能使用
    • newProxyInstance方法的参数:
      • ClassLoader:类加载器
        • 用于加载代理对象字节码,和被代理对象使用相同类加载器-固定写法
      • Class[]:字节码数组-其实就是接口的数组
        • 用于让代理对象和被代理对象有相同的方法-固定写法
      • InvocationHandler:用于提供增强代码
        • 让我们如何写代理的地方。一般用该接口的实现类,或者直接一个匿名内部类
        • 此接口的实现类都是谁用谁写

    main方法:

    final Producer producer=new Producer();
    
    IProducer proxy=(IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() {
        /**
         *
         * @param proxy 代理对象的引用
         * @param method 当前执行的被代理对象的方法
         * @param args 当前方法的参数
         * @return 和被代理对象方法返回值相同
         * @throws Throwable
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Float money=(Float)args[0];
                Object rtValue=null;
                if(method.getName().equals("saleService")) {
                    rtValue = method.invoke(producer, money * 0.8f);
                }
                return rtValue;
    
        }
    });
    
    proxy.saleService(10000f);
    
    • 调用的时候不是直接向厂家调用,而是通过厂家实现的接口调用方法。
    • 调用该接口下的任意方法都会经过invoke方法,而他里面实现了代理商调用厂家的方法,还有些附加服务。这样在代理商调用厂家的方法的时候,就可以动些手脚,加点东西,实现了不修改厂家的方法,但是实现了我们想要的功能。
    • 谁用谁创建,意思就是,谁要添加附加的服务,谁就创建一个代理对象,去代理厂家,这样不修改厂家的方法,但是实现了我们想要的功能。
    • newProxyInstance会返回一个proxy的实例,是以被代理对象的类加载器创建的,实现了特定接口的实例。最后通过接口引用,就可以保证只调用接口中有的方法。

    基于子类的动态代理

    • 涉及的类:Enhancer
    • 提供者:第三方cglib库
    • 如何创建代理对象:
      • 使用Enhancer类的create方法
    • 创建代理对象的要求:
      • 被代理类不能是最终类(没有final修饰)
    • create方法的参数:
      • Class:字节码
        • 用于指定被代理对象的字节码(getClass()获取)
      • Callback(接口):用于提供增强的代码
        • 它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
        • 此接口的实现类都是谁用谁写。
        • 我们一般写的都是该接口的子接口实现类:MethodInterceptor
    final Producer producer=new Producer();
    
    Producer proxy=(Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
        /**
         *
         * @param o
         * @param method
         * @param objects
         * @param methodProxy
         * @return
         * @throws Throwable
         */
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            Float money=(Float)objects[0];
            Object rtValue=null;
            if(method.getName().equals("saleService")) {
                rtValue = method.invoke(producer, money * 0.8f);
            }
            return rtValue;
        }
    });
    
    proxy.saleService(10000f);
    
    • 这里应该是把厂家的子类作为代理对象,父类指向子类对象,上转型,保证了只会调用父类里的方法。同接口约束方法的作用一样。因此需要厂家不是最终类。
    • 别的和用接口做代理对象没区别。

    相关文章

      网友评论

          本文标题:动态代理

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