jdk 动态代理
参考:https://blog.csdn.net/jiankunking/article/details/52143504
一、什么是代理
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制访问。代理类负责为委托类预处理消息,过滤消息,转发消息,以及进行消息被委托类执行后的后续处理。
为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者来看,两者没有区别。通过代理类这一中间层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托对象,同时也为实施不同控制策略预留了空间,从而在设计上获得更大的灵活性。Java 动态代理机制以巧妙的方式完美实践了代理模式的设计理念。
二、Java 动态代理类
Java 动态代理类位于 java.lang.reflect 包下,一般主要涉及以下两个类:
1) interface InvocationHandler:该接口中仅定义一个方法
public Object invoke(Object obj, Method method, Object[] args);
在实际使用是,第一个参数 obj 一般指代理类,method 是被代理方法,args 为该方法的参数数组。这个抽象方法在代理类中动态实现。
2)Proxy:该类即为动态代理类,其中主要有
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException{}
该方法返回代理类的一个实例,返回后的代理类可以当做被代理类使用(可以用被代理类在接口中声明过的方法)
所谓 DynamicProxy 是这样一种 class:它是在运行时生成的 class,在生成它的时候必须提供一组 interfaces 给它,然后该 class 就宣称它实现了这些 interface。当然,这个 DynamicProxy 其实就是一个 Proxy,它不会替你做实质性的工作,在生成它的实例时,你必须提供一个 handler,由它接管实际的工作。
在使用动态代理类时,我们必须实现 InvocationHandler 接口。通过这种方式,被代理的对象可以在运行时动态改变,从而实现了非常灵活的动态代理关系。
动态代理步骤:
- 创建一个实现接口 InvocationHandler 的类,它必须实现 invoke 方法
- 创建被代理的类及接口
- 通过 Proxy 的静态方法 newProxyInstance 创建一个代理
- 通过代理调用方法
三、JDK 动态代理的实现
1. 创建接口
public interface DeptService { void saveDpet(Dept dept); }
2. 创建实现类
public class DeptServiceImpl implements DeptService { @Override public void saveDpet(Dept dept) { System.out.println(" do saveDpet"); } }
3. 创建代理类
public class MyInvocation implements InvocationHandler { private Object target; public MyInvocation(Object target){ this.target = target; } public <T> T getProxy(){ return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new MyInvocation(target)); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(" proxy do before "); method.invoke(target, args); System.out.println(" proxy do After "); return null; } }
4. 调用
@Test public void doProxy(){ DeptService deptService = new MyInvocation(new DeptServiceImpl()).getProxy(); deptService.saveDpet(new Dept()); }
四、动态代理实现原理
生成的代理类调用 saveDept 方法时,为什么会自动调用 InvocationHandlerImpl 的 invoke() 方法?
因为 JDK 生成的最终真正代理类,它继承自 Proxy 并实现了我们定义的 DeptService 方法,在实现 接口方法的内部,通过反射调用了 InvocationHandlerImpl 的 invoke 方法。