java基于接口的动态代理

什么是动态代理:

举个小例子:假如我们要买电脑,如果没有代理,我们会直接找生产厂家购买;

但现在是:代理商找厂家进货,我们是找代理商购买。

用代码讲一下:

1、直接联系生产厂家

IProduce.java


package
com.henu.proxy;

//对生产厂家要求的接口
public interface IProducer { public void sale(float money); public void afterSale(float money); }

Produce.java

package com.henu.proxy;

//一个生产者
public class Producer implements IProducer{

    public void sale(float money) {
        System.out.println("卖出一台电脑,收   "+money);
    }
    public void afterSale(float money) {
        System.out.println("修理一台电脑,收   "+money);
    }
}

Client.java

package com.henu.proxy;

    //模拟一个消费者
    public class Client {


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

            producer.sale(10000f);
        }
    }

假如使用动态代理:只需要对Client.java进行修改:

package com.henu.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方法
        *   创建代理对象的要求:
        *       被代理对象最少实现一个接口,如果没有,则不能用
        *   new ProxyInstance方法的参数:
        *       ClassLoader:类加载器
        *           它用于加载代理对象的字节码。和被代理对象使用相同的类加载器。(固定写法)
        *       Class[]:字节码数组
        *           它用于让代理对象和被代理对象有相同的方法。 (固定写法)
        *       InvocationHandler:用于增强的代码
        *            它是让我们写如何代理。我们一般都是写一个接口的实现类,通常情况下是匿名内部类,但不是必须的。
        *             此接口的实现类是谁用谁写。
        *
        *
        */
        IProducer poxyProducer = (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 ("sale".equals(method.getName())){
                            returnValue = method.invoke(producer,money*0.8f);
                        }
                        return returnValue;
                    }
                });
        poxyProducer.sale(10000f);
    }
}

猜你喜欢

转载自www.cnblogs.com/qzhc/p/11966184.html
今日推荐