JDK的Proxy动态代理用法

1、涉及到的类

  JDK的Proxy动态代理会涉及到以下几个类:
  1、java.lang.reflect.InvocationHandler
  2、java.lang.reflect.Method
  3、java.lang.reflect.Proxy

2、代理流程

2.1 被代理对象的创建

  首先,被代理对象至少实现一个接口。例如有一个演员接口:

package pers.klb.test.proxytest.entities;

/**
 * @Author: Konglibin
 * @Description:
 * @Date: Create in 2020/5/29 14:26
 * @Modified By:
 */
public interface IActor {

    public void basicAct(float money);

    public void dangerAct(float money);
}

  演员接口里面有两个方法,被代理对象实现这两个方法:

package pers.klb.test.proxytest.entities.impl;

import pers.klb.test.proxytest.entities.IActor;

/**
 * @Author: Konglibin
 * @Description:
 * @Date: Create in 2020/5/29 14:27
 * @Modified By:
 */
public class Liudehua implements IActor {
    public void basicAct(float money) {
        System.out.println("刘德华收了"+money+"元钱,做了basicAct。。。");
    }

    public void dangerAct(float money) {
        System.out.println("刘德华收了"+money+"元钱,做了dangerAct。。。");
    }
}

  现在,Liudehua类的对象就是需要被代理的对象。

2.2 InvocationHandler

  java.lang.reflect.InvocationHandler可以理解为包装器,一个增强对象A去代理被代理的对象B,那么A肯定是B经过包装以后生成的。

package pers.klb.test.proxytest.invocationhandler;

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


/**
 * @Author: Konglibin
 * @Description: 代理对象包装器
 * @Date: Create in 2020/5/29 14:31
 * @Modified By:
 */
public class MyInvocationHandler implements InvocationHandler {

    private Object actor;

    public MyInvocationHandler(Object actor) {
        this.actor = actor;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String name = method.getName();
        Float money = (Float) args[0];
        Object rtValue = null;
        //每个经纪公司对不同演出收费不一样,此处开始判断
        if ("basicAct".equals(name)) {
            //基本演出,没有 10 不演
            if (money > 10) {
                //看上去剧组是给了 10,实际到演员手里只有 5
                //这就是我们没有修改原来 basicAct 方法源码,对方法进行了增强
                rtValue = method.invoke(actor, money / 2);
            }
        }
        if ("dangerAct".equals(name)) {
            //危险演出,没有 10 不演
            if (money > 10) {
                //看上去剧组是给了 10,实际到演员手里只有 5
                //这就是我们没有修改原来 dangerAct 方法源码,对方法进行了增强
                rtValue = method.invoke(actor, money / 2);
            }
        }
        return rtValue;
    }
}

  java.lang.reflect.InvocationHandler里面有一个invoke方法,我们写好逻辑后,当我们调用代理对象的方法时,其实就是进入这个invoke方法来执行。

2.3 Proxy

  java.lang.reflect.Proxy就是真正创建代理对象的类,需要输入三个参数:被代理对象的类加载器、被代理对象的接口加载器、InvocationHandler。
  测试方法:

package pers.klb.test.proxytest.demo;

import pers.klb.test.proxytest.entities.IActor;
import pers.klb.test.proxytest.entities.impl.Liudehua;
import pers.klb.test.proxytest.invocationhandler.MyInvocationHandler;

import java.lang.reflect.Proxy;

/**
 * @Author: Konglibin
 * @Description:
 * @Date: Create in 2020/5/29 14:38
 * @Modified By:
 */
public class Demo01 {
    public static void main(String[] args) {
        // 创建原始对象
        Liudehua liudehua = new Liudehua();

        // 运行原始对象
        liudehua.basicAct(20);
        liudehua.dangerAct(30);

        System.out.println("******************");

        // 创建InvocationHandler,输入原始对象
        MyInvocationHandler invocationHandler = new MyInvocationHandler(liudehua);
        IActor target = (IActor) Proxy.newProxyInstance(
                liudehua.getClass().getClassLoader(),
                liudehua.getClass().getInterfaces(),
                invocationHandler
        );

        // 运行代理对象
        target.dangerAct(20);
        target.basicAct(30);
    }
}

3、总结

  创建代理对象的过程很简单:
  1、使用java.lang.reflect.Proxy类的newProxyInstance方法;
  2、输入三个参数:
    (1) 被代理对象的类加载器;
    (2) 被代理对象的接口加载器;
    (3) java.lang.reflect.InvocationHandler实现类;
  我们需要做的就是在java.lang.reflect.InvocationHandlerinvoke方法中把增强逻辑写好。
  调用代理对象的方法时,其实就进入InvocationHandlerinvoke方法中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值