一 ,什么是代理?
代理 : 本来是自己应该做的事, 却请了别人来做, 被请的人就是代理对象
举例 : 春节回家买票找人代买, 黄牛就是代理对象
二 ,什么是动态代理?
代理的对象是变动的, 在程序运行过程中产生的 . 而在程序运行过程中产生对象, 这个对象是不固定的, 那么可以通过反射来实现, 所以动态代理是基于反射实现的.
三 ,动态代理常见有JDK提供的动态代理,和Cglib提供的代理 , 这次介绍JDK提供的代理
1, 在Java中java.lang.reflect包下提供了一个Proxy类和InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象. JDK提供的代理只能针对接口做代理. Cglib提供的代理会更强大一些.
2, Proxy类中的方法创建动态代理类对象,该方法会返回代理类
Public static Object newProxyInstance(ClassLoader loader, Class<?>[] intergaces,InvocationHandler h )
最终会调用InvocationHandler的方法
3, InvocationHandler接口 , 定义动态代理要实现的具体业务逻辑
Object invoke(Objectproxy, Method method , Object[] args );
自定义类实现IncovationHandler接口, 复写invoke()方法, 具体代理的逻辑写在该方法中. invoke()方法执行后的返回值为代理对象 .
代码举例:
1,创建要代理的接口和实现类
1 public interface UserDao { 2 3 void add(); 4 5 void delete(); 6 7 } 8 public class UserDaoImp implements UserDao{ 9 10 public void add() { 11 System.out.println("执行了添加的方法"); 12 } 13 14 public void delete() { 15 System.out.println("执行了删除的方法"); 16 } 17 18 } 19 public interface WorkDao { 20 21 void work(); 22 23 void study(); 24 25 } 26 public class WorkDaoImp implements WorkDao { 27 28 public void work() { 29 System.out.println("工作"); 30 } 31 32 public void study() { 33 System.out.println("学习"); 34 } 35 36 }
2,创建InvocationHandler接口的实现类,具体代理的业务逻辑在Invoke方法
1 /** 2 * 自定义类实现IncovationHandler接口, 复写invoke()方法 3 */ 4 public class MyInvocationHandler implements InvocationHandler { 5 6 private Object target; //目标对象 7 8 public MyInvocationHandler(Object target){ 9 this.target = target; 10 } 11 12 /** 13 * 在代理实例上处理方法调用并返回结果 14 * proxy - 在其上调用方法的代理实例 15 * method - 对应于在代理实例上调用的接口方法的 Method 实例 16 * args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null 17 */ 18 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 19 System.out.println("权限校验"); 20 21 //invoke 方法执行后的返回值为代理类对象 22 Object result = method.invoke(target, args); 23 System.out.println("日志分析"); 24 return result; //返回代理类对象 25 } 26 27 }
3,测试类,Proxy类中的方法创建动态代理类对象,该方法会返回代理类
1 public class ProxyTest { 2 3 /** 4 * 使用JDK动态代理,在原来的方法执行前后执行授权,日志记录 5 * @param args 6 */ 7 public static void main(String[] args) { 8 9 UserDao userDao = new UserDaoImp(); 10 //不使用代理的情况下调用方法 11 userDao.add(); 12 userDao.delete(); 13 14 //代理用户 15 MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userDao); 16 //返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序 17 //返回对象只能是接口UserDao,不能是接口的实现类UserDaoImp,所以说JDK提供的代理只能针对接口做代理 18 UserDao newProxyInstance = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), 19 userDao.getClass().getInterfaces(),myInvocationHandler); 20 21 newProxyInstance.add(); 22 newProxyInstance.delete(); 23 24 25 26 System.out.println("--------------------------------"); 27 28 WorkDao workDao = new WorkDaoImp(); 29 //不使用代理的情况下调用方法 30 workDao.work(); 31 workDao.study(); 32 33 //代理工人 34 MyInvocationHandler myInvocationHandler2 = new MyInvocationHandler(workDao); 35 WorkDao newProxyInstance2 = (WorkDao) Proxy.newProxyInstance(workDao.getClass().getClassLoader(), 36 workDao.getClass().getInterfaces(), myInvocationHandler2); 37 38 newProxyInstance2.work(); 39 newProxyInstance2.study(); 40 41 } 42 43 }
4, 控制台输出 , 在方法执行前后执行了授权和添加日志的方法,具体方法中业务逻辑可以根据实际情况定义
1执行了添加的方法 2执行了删除的方法 3权限校验 4执行了添加的方法 5日志分析 6权限校验 7执行了删除的方法 8日志分析 9-------------------------------- 10工作 11学习 12权限校验 13工作 14日志分析 15权限校验 16学习 17日志分析