常见的动态代理实现主要有两种方法:
一、jdk动态代理,被代理对象必须是基于接口,使用Proxy中的newProxyInstanc()方法
二、cglib动态代理,被代理类不能是最终类(final修饰的类),因为cglib实现的动态代理是基于子类实现的,需要引入第三方jar包cglib,cglib依赖asm,使用EnHancer.create()方法,代码中有介绍
jdk生成动态代理的类:
public class ProxyTool { /** * 需要被代理的类 */ private Object obj; public ProxyTool(Object obj){ this.obj = obj; } /** * Proxy.newProxyInstance()方法有三个参数: * ClassLoader:用于加载代理对象的字节码,与被代理对象的类加载器保持一致,固定写法 * Class[]:字节码数据,用于让代理类与被代理类有相同的方法,固定写法 * InvocationHandler: 用于提供增强的代码,InvocationHandler接口中有一个方法 invoke() * * * invoke中有三个参数: * proxy:代理对象 * method:当前执行的方法 * args:当前执行方法的参数 * @return */ public Object getProxy(){ return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException { //写增强代码的地方 System.out.println("动态代理生效"); return method.invoke(obj,args); } }); } }
cglib生成动态代理:
public class CglibProxy { /** * 被代理对象 */ private Object obj; public CglibProxy(Object obj){ this.obj = obj; } /** * 获取代理对象方法 * 使用cglib中Enhancer.create()方法, * create()方法有两个参数 * Class:字节码,被代理对象的字节码 * Callback;用于写增强代码的接口,一般用其子接口MethodInterceptor * * * @return */ public Object getProxy(){ return Enhancer.create(obj.getClass(), new MethodInterceptor() { /** *注意:intercept()方法中形参的名称o是指代理对象 * @param o 代理对象 * @param method 当前执行的方法 * @param objects 当前执行方法的参数 * @param methodProxy 当前执行方法的代理对象 * @return * @throws Throwable */ public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //写增强的代码 System.out.println("动态代理开启,这是cglib代理"); return method.invoke(obj,objects); } }); } }
测试类:
public class Main { public static void main(String[] args) { //被代理对象 IProxyImpl proxy1 = new IProxyImpl(); //代理工具 //ProxyTool ProxyTool = new ProxyTool(proxy1); CglibProxy cglibProxy = new CglibProxy(proxy1); //获取到代理类,当为jdk代理时不能用用实现类来强转 IProxy proxy = (IProxy)cglibProxy.getProxy(); //执行方法 proxy.print(); } }
使用动态代理时,若被代理的方法抛出异常,代理对象也会抛出异常,但是异常不是原来的异常;
该异常可参考这篇文章:https://www.cnblogs.com/zhaolei1996/p/12435256.html