Java的动态代理

我怕爱的太早我们不能终老 提交于 2020-03-11 01:01:21

1.什么是代理?

看图吧
在这里插入图片描述
在这里插入图片描述

2.JAVA中基于接口的动态代理

一个定义了生产商应该干什么活的接口


public interface IProductor {
    /**
     * 生产
     * @param money
     */
    public void saleProduct(double money);

    /**
     * 售后
     * @param money
     */
    public void afterService(double money);
}

一个生产商

public class Producter implements IProductor{
    /**
     * 生产
     * @param money
     */
    public void saleProduct(double money){
        System.out.println("销售产品,并赚了" + money + "钱");
    }

    /**
     * 售后
     * @param money
     */
    public void afterService(double money){
        System.out.println("提供了售后服务,并赚了" + money + "钱");
    }
}

我们的小明

public class Client {
    public static void main(final String[] args) {
    	//定义一个生产商
        final Producter producter = new Producter();
        //代理对象 proxyProductor来找生产商做代理了
        /**
        *  newProxyInstance方法的参数:
         *      ClassLoader:用于加载代理对象字节码,和被代理对象使用相同的类加载器,代理谁使用谁的类加载器
         *      Class[]:字节码数组,让代理对象和被代理对象有相同的方法,代理谁就写谁
         *      InvocationHandler:用于提供增强的代码,它是让我们写如何代理,我们一般都是写一个该接口的实现类,
         *      通常情况下都是匿名内部类,但不是必须的,此接口的实现类都是谁用谁写
         */
         //通过Proxy.的newProxyInstance创建一个Productor的代理
        IProductor proxyProductor =(IProductor) Proxy.newProxyInstance(producter.getClass().getClassLoader(),
                producter.getClass().getInterfaces(),
                new InvocationHandler() {
                /**
                     * 执行被代理对象的任何接口方法都会经过该方法,拦截接口中的方法
                     * @param o 代理对象的引用
                     * @param method 当前执行的方法
                     * @param objects 当前执行方法所需的参数
                     * @return 和被代理对象有相同的返回值
                     * @throws Throwable
                     */
                    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                        //提供增强的代码
                        Object returnValue = null;
                        //1,获取方法执行的参数
                        Double money = (Double) objects[0];
                        //2.判断当前方法是不是销售
                        if("saleProduct".equals(method.getName())){
                        //使用了代理,在生产商售卖的时候,代理从中间抽取了20%的利润
                            returnValue =  method.invoke(producter,money * 0.8);
                        }
                        return  returnValue;
                    }
                });
        proxyProductor.saleProduct(1000);
    }
}

打印
销售产品,并赚了800.0钱
详细说明

  • 动态代理
  • 特点:字节码随用随创建,随用岁加载,
  • 作用:在不修改源码的基础上对源码进行增强
  • 分类:基于接口的动态代理, 基于子类的动态代理
  • 涉及的类:Proxy
  • 提供者:JDK官方
  • 如何创建代理对象:使用Proxy中的newProxyInstance方法
  • 创建基于接口的代理对象的要求:
    * 被代理类最少实现一个接口,如果没有则不能使用
    * newProxyInstance方法的参数:
    * ClassLoader:用于加载代理对象字节码,和被代理对象使用相同的类加载器,代理谁使用谁的类加载器
    * Class[]:字节码数组,让代理对象和被代理对象有相同的方法,代理谁就写谁
    * InvocationHandler:用于提供增强的代码,它是让我们写如何代理,我们一般都是写一个该接口的实现类,
    * 通常情况下都是匿名内部类,但不是必须的,此接口的实现类都是谁用谁写

2.JAVA中基于子类的动态代理

基于子类的代理需要第三方jar包 cglib
生产商

import com.echo.proxy.IProductor;

public class Producter{
    /**
     * 生产
     * @param money
     */
    public void saleProduct(double money){
        System.out.println("销售产品,并赚了" + money + "钱");
    }

    /**
     * 售后
     * @param money
     */
    public void afterService(double money){
        System.out.println("提供了售后服务,并赚了" + money + "钱");
    }
}

小明

public class Client {
    public static void main(final String[] args) {
        final Producter producter = new Producter();
        Producter cglibProductor = (Producter)Enhancer.create(producter.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 {
                //提供增强的代码
                Object returnValue = null;
                //1,获取方法执行的参数
                Double money = (Double) objects[0];
                //2.判断当前方法是不是销售
                if("saleProduct".equals(method.getName())){
                    returnValue =  method.invoke(producter,money * 0.8);
                }
                return  returnValue;
            }
        });
        cglibProductor.saleProduct(1000);
    }
}

详解
* 涉及的类:Enhancer
* 提供者:第三方cglib库
* 如何创建代理对象:使用Enhancer类中的create方法
* 创建代理对象的要求: 被代理类不能是最终类
* create方法的参数
Class字节码:用于指定被代理对象的字节码
callback:用于提供增强的代码
它是让我们写如何代理,我们一般都是写一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的,此接口的实现类都是谁用谁写,我们一般写的都是该接口的子接口实现类MethodInterceptor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!