动态代理的实现主要包括三部分:
接口:声明业务方法
代理对象:真正对象的代理对象,通过真正对象的业务方法实现抽象类或接口的方法,并可附加自己的业务逻辑
真是对象:实现接口的方法,供代理对象调用
jdk中创建动态代理主要通过java.lang.reflect.Proxy类的
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException)方法。它的第一个参数是真实对象的类加载器,可以通过对象的.getClass().getClassLoader()获取
第二个参数是真实对象实现的接口,可以通过对象的.getClass().getInterfaces()获取
第三个参数是实现InvocationHandler接口的对象,通过api可知InvocationHandler是代理实例的调用处理程序 实现的接口,主要用于监听代理对象调用方法来调用真实对象的方法,它底层采用的是观察者模式。
InvocationHandler接口是一个函数式接口,它只有一个invoke(Object proxy, Method method, Object[] args)
方法,当代理对象调用方法时,会执行此方法。它的
第一个参数是代理对象
第二个参数是真实对象要调用方法,即调用的方法对象
第三个对象是调用方法的参数
如下:
首先创建一个接口:
public interface ITarget {
public void show();
}
真实对象实现接口:
public class Target implements ITarget {
@Override
public void show() {
System.out.println("-----------------show");
}
}
创建代理对象调用真实对象接口:
@Test
public void test1() {
//System.out.println("------------");
ITarget target = new Target();
//创建代理对象
ITarget targetProxy = (ITarget) Proxy.newProxyInstance(
target.getClass().getClassLoader(), //真实对象的类加载器
target.getClass().getInterfaces(), //真实对象实现的接口
(Object proxy, Method method, Object[] args) -> {
System.out.println("附加的功能...日志、开启事务等等");
Object object = method.invoke(target, args);//调用真实目标方法,参数1为真实对象
System.out.println("附加的功能...结束时间、提交事务等等");
return object;
}
);
targetProxy.show();//代理对象调用方法。
}
当代理对象调用show()方法时,会执行InvocationHandler实现类中的invoke方法,并将代理对象传入invoke方法proxy参数,将要执行的方法传入method,并将方法参数传入args。而此时invoke方法真正调用真实对象方法的是method.invoke方法(第一个参数为真实对象,第二个参数为真实对象方法的参数,即InvocationHandler实现类中的invoke方法中的args),而在执行此方法是可以在此方法前后添加附加功能。当然在执行method.invoke一般会用Object来接收返回值,这样当真实对象执行后有返回值时这样代理对象也会接收到返回值。