• 动态代理回顾


    1.动态代理回顾

    1.1动态代理的特点

    1.2基于接口的动态代理

    1.接口

    package com.itheima.proxy;
    
    /**
     * 对生产厂家要求的接口
     */
    public interface IProducer {
    
        /**
         * 销售
         * @param money
         */
         void saleProduct(float money);
    
        /**
         * 售后
         * @param money
         */
         void afterService(float money);
    }

    2.目标类

    package com.itheima.proxy;
    
    /**
     * 一个生产者
     */
    public class Producer  implements IProducer {
        /**
         * 销售
         * @param money
         */
        @Override
        public void saleProduct(float money){
            System.out.println("销售产品,并拿到钱:"+money);
        }
    
        /**
         * 售后
         * @param money
         */
        @Override
        public void afterService(float money){
            System.out.println("提供售后服务,并拿到钱:"+money);
        }
    }

    3.测试方法

    package com.itheima.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class Client {
        public static void main(String[] args){
            final Producer producer = new Producer();
    
            /**
             * 动态代理:
             *  特点:字节码随用随创建,随用随加载
             *  作用:不修改源码的基础上对方法增强
             *  分类:
             *      基于接口的动态代理
             *      基于子类的动态代理
             *  基于接口的动态代理:
             *      涉及的类:Proxy
             *      提供者:JDK官方
             *  如何创建代理对象:
             *      使用Proxy类中的newProxyInstance方法
             *  创建代理对象的要求:
             *      被代理类最少实现一个接口,如果没有则不能使用
             *  newProxyInstance方法的参数:
             *      ClassLoader:类加载器
             *          它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。
             *      Class[]:字节码数组
             *          它是用于让代理对象和被代理对象有相同方法。固定写法。
             *      InvocationHandler:用于提供增强的代码
             *          它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
             *          此接口的实现类都是谁用谁写。
             */
            IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(),
                    producer.getClass().getInterfaces(),
                    new InvocationHandler() {
                        /**
                         * 作用:执行被代理对象的任何接口方法都会经过该方法
                         * 方法参数的含义
                         * @param proxy   代理对象的引用
                         * @param method  当前执行的方法
                         * @param args    当前执行方法所需的参数
                         * @return        和被代理对象方法有相同的返回值
                         * @throws Throwable
                         */
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            //提供增强的代码
                            Object returnValue = null;
    
                            //1.获取方法执行的参数
                            Float money = (Float)args[0];
                            //2.判断当前方法是不是销售
                            if("saleProduct".equals(method.getName())) {
                                returnValue = method.invoke(producer, money*0.8f);
                            }
                            return returnValue;
                        }
                    });
            proxyProducer.saleProduct(10000f);
        }
    }

    1.3基于子类的动态代理

    1.导入cglib的jar包

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.itheima</groupId>
        <artifactId>day03_eesy_proxy2</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <dependencies>
            <dependency>
                <groupId>org.sonatype.sisu.inject</groupId>
                <artifactId>cglib</artifactId>
                <version>2.2.1-v20090111</version>
            </dependency>
        </dependencies>
    
    </project>

    2.目标类

    package com.itheima.cglib;
    
    /**
     * 一个生产者
     */
    public class Producer {
    
        /**
         * 销售
         * @param money
         */
        public void saleProduct(float money){
            System.out.println("销售产品,并拿到钱:"+money);
        }
    
        /**
         * 售后
         * @param money
         */
        public void afterService(float money){
            System.out.println("提供售后服务,并拿到钱:"+money);
        }
    }

    3.代理类

    package com.itheima.cglib;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * 模拟一个消费者
     */
    public class Client {
    
        public static void main(String[] args) {
            final Producer producer = new Producer();
    
            /**
             * 动态代理:
             *  特点:字节码随用随创建,随用随加载
             *  作用:不修改源码的基础上对方法增强
             *  分类:
             *      基于接口的动态代理
             *      基于子类的动态代理
             *  基于子类的动态代理:
             *      涉及的类:Enhancer
             *      提供者:第三方cglib库
             *  如何创建代理对象:
             *      使用Enhancer类中的create方法
             *  创建代理对象的要求:
             *      被代理类不能是最终类
             *  create方法的参数:
             *      Class:字节码
             *          它是用于指定被代理对象的字节码。
             *
             *      Callback:用于提供增强的代码
             *          它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
             *          此接口的实现类都是谁用谁写。
             *          我们一般写的都是该接口的子接口实现类:MethodInterceptor
             */
            Producer cglibProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
                /**
                 * 执行北地阿里对象的任何方法都会经过该方法
                 * @param proxy
                 * @param method
                 * @param args
                 *    以上三个参数和基于接口的动态代理中invoke方法的参数是一样的
                 * @param methodProxy :当前执行方法的代理对象
                 * @return
                 * @throws Throwable
                 */
                @Override
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    //提供增强的代码
                    Object returnValue = null;
    
                    //1.获取方法执行的参数
                    Float money = (Float) args[0];
                    //2.判断当前方法是不是销售
                    if ("saleProduct".equals(method.getName())) {
                        returnValue = method.invoke(producer, money * 0.8f);
                    }
                    return returnValue;
                }
            });
            cglibProducer.saleProduct(12000f);
        }
    }

  • 相关阅读:
    PostMan-NewMan运行参数
    shell脚本学习简单记录笔记
    android开发okhttp-4.9.1源码大致流程解读
    android开发获取键盘高度以及判断键盘是否显示(兼容分屏模式)
    Android开发The style on this component requires your app theme to be Theme.AppCompat (or a descendant)的解决方法
    Linux开发Ubuntu安装man手册
    Android开发源码解读四大组件源码解读简单梳理
    Android开发涉及到的AMS类和ActivityThread类源码解读
    Android开发为什么主线程可以一直运行而不会退出来
    前端CryptoJS加密、后端解密代码实现参考
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/12115635.html
Copyright © 2020-2023  润新知