我随意写,你随意看。

林老头儿

但愿绝望和无奈远走高飞

Fork me on Gitee

Java动态代理

  1. 特点:字节码随用随创建,随用随加载。(不同于装饰模式)

  2. 作用:不修改源码的基础上对方法增强

  3. 分类:

    1. 基于接口的动态代理
    2. 基于子类的动态代理
  4. 基于接口的动态代理:

    1. 涉及的类:Proxy;提供者:JDK官方
    2. 如何创建代理对象:使用Proxy类中的newProxyInstance方法
    3. 创建代理对象的要求:被代理类最少实现一个接口,如果没有则不能使用
    4. newProxyInstance方法的参数:
      1. ClassLoader :它是用于加载代理对象字节码的,和被代理对象使用相同的类加载器
      2. Class<?>[] :它是用于让代理对象和被代理对象有相同方法
      3. InvocationHandler :它是让我们写如何代理,我们一般都是写一个该接口的实现类,通常情况下都是使用匿名内部类,此接口的实现类都是谁用谁写。
    5. 最主要的是去实现InvocationHandler 中的invoke方法。
        public static void main(String[] args)
        {
            final Producer producer = new Producer();
    
            IProducer iProducer = (IProducer) Proxy.newProxyInstance(Producer.class.getClassLoader(), Producer.class.getInterfaces(), new InvocationHandler()
            {
                /**
                 * 作用:执行被代理对象的任何接口方法都会经过该方法
                 * @param proxy     代理对象的引用
                 * @param method    当前执行的方法
                 * @param args      当前执行方法所需要的参数
                 * @return 和被代理对象方法有相同的返回值
                 * @throws Throwable
                 */
                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()))
                    {
                        System.out.println("代理商获取0.2的利润");
                        returnValue = method.invoke(producer, money * 0.8f);
                    }
                    return returnValue;
                }
            });
    
            iProducer.saleProduct(1000f);
        }
    
  5. 基于子类的动态代理

    1. 导入jar包:cglib
    2. 涉及的类:Enhancer,提供商:第三方cglib库
    3. 如何创建代理对象:使用Enhancer类中create方法
    4. 创建代理类的要求:被代理类不能是最终类
    5. create方法的参数:
      1. Class:它是用于加载代理对象字节码的,和被代理对象使用相同的类加载器
      2. Callback:它是让我们写如何代理,我们一般都是写一个该接口的实现类,通常情况下都是使用匿名内部类。我们一般写该接口的子接口实现类:MethodInterceptor
        public static void main(String[] args)
        {
            final Producer producer = new Producer();
    
            Producer proxyProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor()
            {
                /**
                 * 执行被代理对象方法都会经过该方法
                 * @param proxy
                 * @param method
                 * @param args
                 *      以上三个参数和基于接口实现动态代理一样
                 * @param methodProxy   当前执行方法的代理对象
                 * @return
                 * @throws Throwable
                 */
                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()))
                    {
                        System.out.println("代理商获取0.2的利润");
                        returnValue = method.invoke(producer, money * 0.8f);
                    }
                    return returnValue;
                }
            });
    
            proxyProducer.saleProduct(1000f);
        }
    
posted @ 2019-11-02 17:54  林老头儿  阅读(142)  评论(0编辑  收藏  举报