代理

我们经常需要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法和运行时间、事务管理等等。

为此我们可以编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码,在访问者看来,两者没有任何区别。通过代理类这中间一层,能有效控制对目标类对象的直接访问,也可以很好地隐藏和保护目标类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。这是一种设计模式,被称之为代理。代理是AOP(Aspect oriented program,面向切面编程)的关键技术。

如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后就很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易。

动态代理

静态代理就是在源码阶段就为为系统中的各种接口的类增加代理功能,如果这样做,将需要非常多的代理类。 JVM可以在运行期间动态生成类的字节码,这种动态生的类往往被用作代理类,即动态代理

  • JVM生成的动态代理类必须实现至少一个接口, JVM生成的动态类只能用作具有相同接口的目标类的代理。
  • CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,可以使用CGLIB类。
  • 代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中调用目标方法前后处理目标方法异常的catch块中加上系统功能代码。

代理机制和特点

Java动态代理主要涉及以下几个类:

  • java.lang.reflect.Proxy Java动态代理机制的主类,提供了一组静态方法来为一组接口动态地生成代理类及其对象。其中最重要的一个静态方法如下,该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
  • java.lang.reflect.InvocationHandler 这是调用处理器接口,它自定义了一个invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对目标类的代理访问。每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象(参见上文中列出的Proxy类的静态方法)。
// 该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象,第三个方法是调用参数。
// 调用处理器根据这三个参数进行预处理或分派到目标类实例上发射执行
Object invoke(Object proxy, Method method, Object[] args)
  • java.lang.ClassLoader 这是类加载器类,负责将类的字节码装载到JVM中并为其定义类对象,每次生成动态代理类对象时都需要指定一个类装载器对象(参见上文中列出的Proxy类的静态方法)。

使用Java动态代理的具体步骤如下:

  1. 通过实现 InvocationHandler 接口创建自己的调用处理器
  2. 通过 Proxy 类创建动态代理类实例,创建实例时调用处理器对象作为参数被传入
// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到目标类的分派转发
InvocationHandler handler = new InvocationHandlerImpl(..);
// 通过 Proxy 直接创建动态代理类实例
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader, new Class[] { Interface.class }, handler );

下面给出一个创建动态代理类实例的例子,可以直接运行

自定义接口Advice

package com.crow.Proxy;import java.lang.reflect.*;/** * Created by CrowHawk on 17/2/20. */
public interface Advice {void forwardMethod(Method method);void backMethod(Method method);
}

实现了Advice接口的类AdviceImpl

package com.crow.Proxy;import java.lang.reflect.Method;/** * Created by CrowHawk on 17/2/20. */
public class AdviceImpl implements Advice {long beginTime = 0;public void forwardMethod(Method method){System.out.println("end");beginTime = System.currentTimeMillis();}public void backMethod(Method method){System.out.println("start");long endTime = System.currentTimeMillis();System.out.println(method.getName() + " running time of " + (endTime - beginTime));}
}

ProxyTest.java

package com.crow.Proxy;import java.lang.reflect.*;
import java.util.*;
import java.util.Collection;/** * Created by CrowHawk on 17/2/20. */
public class ProxyTest {public static void main(String args[]){ArrayList<String> target = new ArrayList<>();//创建目标类的实例对象AdviceImpl adviceImpl = new AdviceImpl();Collection proxy = (Collection) getProxy(target, adviceImpl);//创建动态类proxy.add("aa");System.out.println(proxy.size());System.out.println(proxy.getClass().getName());}public static Object getProxy(final Object target, final Advice advice){Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {//动态类通过Invocation类的invoke方法调用目标类所需的方法public Object invoke(Object proxy, Method method, Object[] args) throws Exception {advice.forwardMethod(method);Object retVal = method.invoke(target, args);advice.backMethod(method);return retVal;}});return proxy;}
}

Java基础学习(4)-动态代理相关推荐

  1. 学习Spring必学的Java基础知识(2)----动态代理

    Spring AOP使用动态代理技术在运行期织入增强的代码,为了揭示Spring AOP底层的工作机理,有必要对涉及到的Java知识进行学习.Spring AOP使用了两种代理机制:一种是基于JDK的 ...

  2. Java基础之02 动态代理模式172 173 类加载器原理分析

    动态代理 所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect ...

  3. 【Java基础】基于动态代理优雅高性能的拷贝对象?BeanCopier

    1.场景:微服务层与层之间进行对象的拷贝 微服务里面为了代码层次结构清晰,一般会进行分层,DAO层,Servic层,Controller.不同层使用不同后缀对象来进行数据传递 DAO层一般会使用 DO ...

  4. Java 反射机制和动态代理是基于什么原理,了解过吗?

    工作多年以及在面试中,我经常能体会到,有些面试者确实是认真努力工作,但坦白说表现出的能力水平却不足以通过面试,通常是两方面原因: 1."知其然不知其所以然". 做了多年技术,开发了 ...

  5. 尚学堂JAVA基础学习笔记_2/2

    尚学堂JAVA基础学习笔记_2/2 文章目录 尚学堂JAVA基础学习笔记_2/2 写在前面 第10章 IO技术 1. IO入门 2. IO的API 3. 装饰流 4. IO实战 5. CommonsI ...

  6. java底层 —反射、动态代理

    java底层 -反射.动态代理和注解 1. 反射介绍 1.1 反射 反射是指程序可以访问,检测,修改它本身状态或行为的一种能力. 1.2 java的反射机制 java的反射机制是指在程序运行状态中,给 ...

  7. JAVA基础学习精简心得笔记整理

    JAVA基础学习精简心得笔记整理 配置java环境变量 Java的运行过程  基本数据类型 引用数据类型 逻辑运算符 数组 方法重载 封装 继承 多态 多态的作用 单例设计模式 接口interface ...

  8. java基础学习整理(一)

    java基础学习整理(一) lesson1: D0s命令: 1.回到根目录,>cd \ 2.复制命令行下的内容,右击标记所要复制的内容,这样就已经复制好了,右击粘贴就可以了. 3.查看,设置环境 ...

  9. Java中大数据数组,Java基础学习笔记之数组详解

    摘要:这篇Java开发技术栏目下的"Java基础学习笔记之数组详解",介绍的技术点是"java基础学习笔记.基础学习笔记.Java基础.数组详解.学习笔记.Java&qu ...

  10. Java基础学习——第十四章 网络编程

    Java基础学习--第十四章 网络编程 一.网络编程概述 计算机网络: 把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大.功能强的网络系统,从而使众多的计算机可以方便地互相传递信 ...

最新文章

  1. deepin系统引导_国产 Linux 发行版 深度操作系统 20 正式版发布
  2. linux之使用帮助
  3. Jetson Nano 改成国内源(中科大源)
  4. 如何运用领域驱动设计 - 领域服务
  5. DNGuard HVM 专业版 v2.7 正式发布。
  6. gevent 协程 使用
  7. 代码管理学:凡事养成登记的做法,比如依赖库
  8. ios 定位权限获取
  9. MUI框架学习(2)-页面间传值
  10. 出现问题请与你的系统管理员联系 照片出现问题请与你的系统管理员 照片出现问题请与系统管理员联系 无法打开应用请与管理员联系
  11. mac虚拟机(windows10)装powerdesigner界面模糊或图形菜单很小问题
  12. Excel读写工具类
  13. 关于spyder环境配置
  14. 菜鸟自学02:下载参考基因组及构建bowtie2索引
  15. 1.3.9 python中进程与线程
  16. 使用Cocos Creator制作试玩广告(PlayableAd)
  17. 我们工作到底为了什么?---惠普前中国区总裁的感悟
  18. Layui+Servlet+MyBatis+Mysql实现的大学生创新竞赛管理平台
  19. html中模块怎么创建,在Joomla中创建一个自定义HTML模块,不显示
  20. 视频号怎么在扩展链接中添加京东联盟、拼多多带货链接

热门文章

  1. 6. php 基本语法
  2. 变频器22b系列说明书_变频器接电位器正确接法
  3. Hadoop运行时缺少hadoop dll winutils exe
  4. 工具使用-curl/wget
  5. Djangon 基础总结 汇总 从请求到返回页面的过程,
  6. 13.2 处理静态资源【从零开始学Spring Boot】
  7. 用shell查找某目录下的最大文件
  8. php实现单,双向链表,环形链表解决约瑟夫问题
  9. @property 参数问题
  10. 转载 java序列化与反序列化