在我的前一篇博文静态代理中,使用静态代理模式时,我们需要在程序加载执行前,手动的创建好每个目标对象类的代理类。这样就导致我们如果有很多个需要被代理的类时,就必须手动的去创建好所有的每一个代理类,这样就会生成很多的代理文件,不易于代理的维护和管理。有没有什么办法可以不用生成这么多代理类呢?动态代理
一 什么是动态代理
代理类在程序运行时才被创建出来的方式称为动态代理。在这种方式中,我们不需要在程序执行前去生成对应的代理类,只需要在程序执行过程中,根据我们传递的目标对象去动态的创建即可。相比较静态代理,这种方式不需要我们去手动创建大批量的文件,更易于代理对象及方法的统一管理维护,比如我们需要对代理类做方法增强时就不需要去修改每一个代理类。
二 动态代理实现
创建两个接口
1 public interface ICatDao { 2 3 /** 4 * 描述自己 5 */ 6 void desc(); 7 8 }
1 public interface IDogDao { 2 3 /** 4 * 描述自己 5 */ 6 void desc(); 7 8 }
创建接口的实现类
1 public class CatDaoImpl implements ICatDao { 2 @Override 3 public void desc() { 4 System.out.println("<<-----------喵喵----------->>"); 5 } 6 }
1 public class DogDaoImpl implements IDogDao { 2 @Override 3 public void desc() { 4 System.out.println("<<-----------旺旺----------->>"); 5 } 6 }
创建动态代理类实现 InvocationHandler接口(JDK动态代理必须实现这个接口),我们使用提供的目标对象调用getProxy方法来生成代理类,执行目标对象提供的方法时会通过反射执行invoke方法执行
1 public class DynamicProxy implements InvocationHandler { 2 3 /** 4 * 目标对象 5 */ 6 private Object target; 7 8 public DynamicProxy() { 9 } 10 11 public Object getProxy(Object intf){ 12 this.target = intf; 13 //args1:类加载器 14 //args2:目标对象接口方法 15 //InvocationHandler接口。所有动态代理类的方法调用,都会交由InvocationHandler接口实现类里的invoke()方法去处理 16 return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this); 17 } 18 19 @Override 20 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 21 method.invoke(target, args); 22 return null; 23 } 24 25 }
测试,创建main方法生成代理类,执行方法
1 public static void main(String[] args) { 2 3 ICatDao catDao = new CatDaoImpl(); 4 ICatDao catDaoProxy = (ICatDao) new DynamicProxy().getProxy(catDao); 5 catDaoProxy.desc(); 6 7 IDogDao dagDao = new DogDaoImpl(); 8 IDogDao dagDaoProxy = (IDogDao) new DynamicProxy().getProxy(dagDao); 9 dagDaoProxy.desc(); 10 11 }
执行结果如下,可以看到动态的生成了每一个目标对象,且可以正常执行
如果我们需要对做方法增强,我们只需要修改invoke就可以了,如
1 @Override 2 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 3 System.out.println("方法【"+method.getName()+"】要开始执行了"); 4 method.invoke(target, args); 5 System.out.println("方法【"+method.getName()+"】已经执行结束"); 6 return null; 7 }
执行测试方法,结果如下,可以看到对所有的代理类的方法都做了增强
原文:https://www.cnblogs.com/love-wzy/p/10175151.html