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.InvocationHandler
的invoke
方法中把增强逻辑写好。
调用代理对象的方法时,其实就进入InvocationHandler
的invoke
方法中。