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);
    }
}

 

 

二、基于子类的动态代理

 拷贝Produce.java类

package com.henu.cglib;

import com.henu.proxy.IProducer;
//一个生产者
public class Producer{

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

基于子类的动态代理

Client.java

package com.henu.cglib;

import com.henu.proxy.IProducer;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

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();
        /**
        * 动态代理:
        *   特点:字节码随用随创建,随用随加载
        *   作用:不修改源码的基础上对方法增强
        *   分类:
        *       基于接口的动态代理
        *       基于子类的动态代理
        *   写的是基于子类的动态代理:
        *       设计的类:Enhancer
        *       提供者:cglib库
        *   如何创建代理对象:
        *       使用Enhancer类中的create方法
        *   创建代理对象的要求:
        *       被代理对象不能是最终类
        *   newProxyInstance方法的参数:
        *       Class:字节码
        *           它用于指定被代理对象的字节码
        *       Callback:用于提供增强的代码
        *           它是让我们写如何代理。我们一般都是写该接口的实现类,通常是匿名内部类,但不是必须的。
        *           此接口的实现类都是谁用谁写的
        *           我们一般写的都是该类的子接口实现类:MethodInterceptor
        */

        Producer cglibProduce = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                /**
                     *作用:执行被代理对象的任何接口方法都会经过该方法
                     *方法参数的定义:
                     * @param o             代理对象的引用
                     * @param method        当前执行的方法
                     * @param objects       当前执行方法所需的参数
                     * @param methodProxy   当前执行方法的代理对象
                     * @return              和被代理对象方法具有相同的返回值
                        * @throws Throwable
                        */
                //提供增强的代码
                Object returnValue = null;
                //1.获取方法执行的参数
                float money = (Float) objects[0];
                //2.判断当前方法是不是销售
                if ("sale".equals(method.getName())){
                    returnValue = method.invoke(producer,money*0.8f);
                }
                return returnValue;
            }
        });
        cglibProduce.sale(20000f);
    }
}

 

posted on 2019-12-01 15:21  Hi,Bro  阅读(188)  评论(0编辑  收藏  举报