Java中的动态代理


当我们在写代码中需要对源码的方法进行增强,但是我们又不可以改源码。这个时候我们就可以使用代理的方式,当然代理的方式:静态代理和动态代理。但是静态代理我们需要创建很多代理类很是繁琐,而动态代理就是,随用随创建,随用随加载。动态代理可以分为:基于接口的动态代理,基于子类的动态代理。
在B站看到黑马老师讲的动态代理,推荐去看下。

基于接口的动态代理

基于接口的动态代理可以使用JDK官方提供的Proxy类,该类的newProxyInstance方法。
newProxyInstance方法的参数:

  • ClassLoader:类加载器
    • 它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。
  • Class[]:字节码数组
    • 它是用于让代理对象和被代理对象有相同方法。固定写法。
  •  InvocationHandler:用于提供增强的代码
    
    • 它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。此接口的实现类都是谁用谁写。

下面是我们创建的三个类:Produce是工厂实现类,他实现了IProduce接口,
IProduce是工厂所需要满足的规范。client是一个客户。之前客户需要买一个东西可以直接找到厂商,可以直接购买。而现在厂商不在负责个人销售和售后,而是交给了经销商,现在客户购买商品就要从经销商出,所有的售后也直接找经销商。经销商就可以看做工厂的代理类,它需要强化工厂的一些方法。
在这里插入图片描述
IProduce

package proxy;

/**
 * @File :   IProduce.Java
 * @Modify Time      @Author    @Version    @Desciption
 * ------------      -------    --------    -----------
 * 2021-01-06           yudong      1.0         None
 */
public interface IProduce {
    /**
     * 销售
     *
     * @param money
     */
    public void saleProduct(float money);

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

Produce

package proxy;

/**
 * @File :   Produce.Java
 * @Modify Time      @Author    @Version    @Desciption
 * ------------      -------    --------    -----------
 * 2021-01-06           yudong      1.0         None
 */
public class Produce implements IProduce {
    /**
     * 销售
     *
     * @param money
     */
    @Override
    public void saleProduct(float money) {
        System.out.println("销售产品,并拿到钱" + money);
    }

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

Client:我们假设经销商需要抽成20%

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @File :   Client.Java
 * @Modify Time      @Author    @Version    @Desciption
 * ------------      -------    --------    -----------
 * 2021-01-06           yudong      1.0         None
 */
public class Client {
    public static void main(String[] args) {
        Produce produce = new Produce();
        
        IProduce proxyProduce = (IProduce) Proxy.newProxyInstance(produce.getClass().getClassLoader(),
                produce.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 reValue = null;
                        float money = (float) args[0];
                        if ("saleProduct".equals(method.getName())) {
                            reValue = method.invoke(produce, money * 0.8f);
                        }
                        return reValue;
                    }
                });
        proxyProduce.saleProduct(10000);
    }
}

基于子类的动态代理

基于子类的动态代理不可是由final修饰的类,即不可被继承的类。其实写动态代理主要就是写动态代理的方法。

package cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import proxy.IProduce;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @File :   Client.Java
 * @Modify Time      @Author    @Version    @Desciption
 * ------------      -------    --------    -----------
 * 2021-01-06           yudong      1.0         None
 */
public class Client {
    public static void main(String[] args) {
        Produce produce = new Produce();
        /**
         * 动态代理:
         *  特点:字节码随用随创建,随用随加载
         *  作用:不修改源码的基础上对方法增强
         *  分类:
         *      基于接口的动态代理
         *      基于子类的动态代理
         *  基于子类的动态代理:
         *      涉及的类:Enhancer
         *      提供者:第三方cglib库
         *  如何创建代理对象:
         *      使用Enhancer类中的create方法
         *  创建代理对象的要求:
         *      被代理类不能是最终类
         *  create方法的参数:
         *      Class:字节码
         *          它是用于指定被代理对象的字节码。
         *
         *      Callback:用于提供增强的代码
         *          它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
         *          此接口的实现类都是谁用谁写。
         *          我们一般写的都是该接口的子接口实现类:MethodInterceptor
         */
        Produce proxyProduce = (Produce) Enhancer.create(produce.getClass(),
                new MethodInterceptor() {
                    /**
                     *
                     * @param o     代理对象的引用
                     * @param method  当前执行的方法
                     * @param objects   当前执行方法所需的参数
                     * @param methodProxy   当前执行方法的代理对象
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        //提供增强的代码
                        Object reValue = null;
                        float money = (float) objects[0];
                        if ("saleProduct".equals(method.getName())) {
                            reValue = method.invoke(produce, money * 0.8f);
                        }
                        return reValue;
                    }
                }
        );
        proxyProduce.saleProduct(10000);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值