记录Kite的学习历程之动态代理

Kite学习框架的第九天

今天穿插讲一下两个方式的动态代理
1.基于接口的动态代理
2.基于子类的动态代理

1. 基于接口的动态代理

1.1首先创建一个生产厂商类

含有两个方法
1.销售商品
2.提供售后服务

package cn.kitey.proxy;


/**
 * 一个生产厂家
 */
public class Producer implements ProducerInterface{

    /**
     * 销售
     */
    public void saleProduct(double money){
        System.out.println("销售产品,获取金钱:" + money);
    }

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


1.2 创建一个消费者类Client

现在创建的一个类:代表消费者直接在厂商购买商品
现在产生了一个需求:
厂商与消费者之间产生了经销商,则通过经销商,生产厂家只能拿到消费者消费数额的百分之八十,所以我们这时可以使用动态代理

关于动态代理的注解都在下面代码中:
我强调一下最重要的就是填写动态代理的增强方法
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}


package cn.kitey.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) {
        //匿名内部类访问时要求是最终的
        Producer producer = new Producer();


       producer.saleProduct(1000);


    }


}

添加了基于接口的动态代理类

package cn.kitey.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
         *  如何创建代理对象:
         *      使用Proxy类中的newProxyInstance
         *  创建代理对象的要求:
         *      被代理的对象至少实现一个接口,如果没有,则不能进行实现
         *   newProxyInstance中的方法参数
         *      ClassLoader:类加载器
         *          适用于加载代理对象的字节码,和被带你的对象使用相同的类加载器(固定写法)
         *      Class[]:字节码数组
         *          是用于代理对象和被代理对象拥有相同的方法(固定的写法)
         *      InvocationHandler:用于提供增强的代码
         *          让我们写如何代理,一般都是些一个接口的实现类,通常情况下是匿名类,但不是必须的
         *          此接口的实现类谁用谁写
         */
        //(近似于经销商)
         ProducerInterface producerInterface  = (ProducerInterface) 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 {
                        //获取以前的金钱数据
                        double oldMoney = (Double) args[0];
                        //提供增强代码
                        Object newMoney = null;
                        //判断是不是销售产品
                        if("saleProduct".equals(method.getName())){
                            newMoney = method.invoke(producer, oldMoney * 0.8);
                        }
                        return  newMoney;
                    }
                });


        /**
         * 现在存在一个需求,经过了经销商,产家只能获取百分之八十的钱
         */
        producerInterface.saleProduct(1000);





    }

}

实现了动态代理后的运行结果图:
记录Kite的学习历程之动态代理_第1张图片

2.基于子类的动态代理

2.1 这时我们需要导入第三方jar包cglib

<dependencies>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.1_3</version>
        </dependency>
    </dependencies>

2.2 创建Cglib的动态代理类

其中使用Enhancer类中的create方法进行对象的代理
create中只用两个参数
class(字节码), Callback(提供代码的增强)
new MethodInterceptor()方法增强的内部类


package cn.kitey.cglib;

import cn.kitey.proxy.Producer;
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 ClientCglib {


    public static void main(String[] args) {
        final Producer producer = new Producer();

        /**
         *  基于子类的动态代理;
         *      涉及的类:Enhancer
         *      提供者:第三方cglib类库
         *  如何创建代理对象:
         *      使用Enhancer类中的create方法
         *  创建代理对象的要求:
         *      被代理的对象不能是最终实现类
         *   create方法中的方法参数
         *      Class:字节码
         *           用于指定被代理对象的字节码
         *   Callback:提供增强代码
         *          一般书写的为该接口的实现类:MethodInterceptor(方法拦截)
         *
         */
        Producer proEnhancer= (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 newMoney = null;
                //获取被代理对象的参数
                double oldMoney = (Double) args[0];
                //判断执行的方法
                if("saleProduct".equals(method.getName())){
                    newMoney = method.invoke(producer, oldMoney * 0.5);
                }
                return newMoney;
            }
        });

        proEnhancer.saleProduct(1000);
    }
}

这个是生产者只拿到了百分之五十的消费者消费的数额
运行结果图:
记录Kite的学习历程之动态代理_第2张图片

以上就是一个简单的动态代理的讲解,希望我们都能变的更加优秀!

你可能感兴趣的:(记录Kite的学习历程之动态代理)