JAVA动态代理 你真的完全了解Java动态代理吗?
网上讲JAVA动态代理,说的天花乱坠,发现一篇文章写的通俗易懂,特意转载过来
原文地址:https://www.jianshu.com/p/95970b089360
例子
一个程序员Developer,他会开发code,他调试debug。

程序员有很多分类,其中有Java程序员JavaDeveloper,他会开发Java代码,会调试Java代码。

Zack的这种“特异功能”是后天练出来的,并没有哪种程序员有这种特性。虽然我们也可以定义一个拥有这样特性的程序员,但是拥有各种乱七八糟特性的程序千千万。我们什么时候才能定义完,而能保证不漏呢?
其实我们没有必要去定义他,因为他是后天养成的,我们应该在这个程序员的成长期去实现这个特性,而不是在他出生之前定义。
我们来看下代码是怎么实现的。

如果Zack只是一个普通的Java程序员,那么他的开发结果是
Zack is coding java
Zack is debugging java
但是真正的Zack(代理后)
Zack is praying for the code!
Zack is coding java
Zack's have no bug!No need to debug!
Proxy.newProxyInstance()
回看下上面是如何使用动态代理的使用。生成一个实例对象,然后用Proxy的newInstance方法对这个实例对象代理生成一个代理对象。

这里有一个非常关键的人,也是比较少人去理解它的。为什么要传zack的类加载和zack的接口呢?
有没有留意到zackProxy的类型是Developer接口,而不是一个实现类。因为zack在被代理后生成的对象,并不属于Developer接口的任何一个实现类。但是它是基于Developer接口和zack的类加载代理出来的。
看下newProxyInstance()的接口定义

这三个参数具体的含义来看看注解是怎么描述的

- loder,选用的类加载器。因为代理的是zack,所以一般都会用加载zack的类加载器。
- interfaces,被代理的类所实现的接口,这个接口可以是多个。
- h,绑定代理类的一个方法。
loder和interfaces基本就是决定了这个类到底是个怎么样的类。而h是InvocationHandler,决定了这个代理类到底是多了什么功能。所以动态代理的内容重点就是这个InvocationHandler。
InvocationHandler

根据注解描述可知,InvocationHandler作用就是,当代理对象的原本方法被调用的时候,会绑定执行一个方法,这个方法就是InvocationHandler里面定义的内容,同时会替代原本方法的结果返回。
InvocationHandler接收三个参数
- proxy,代理后的实例对象。
- method,对象被调用方法。
- args,调用时的参数。
在上面的例子里,

如果最后的return语句改成
return method.invoke(proxy, agrs);
invoke的对象不是zack,而是proxy,根据上面的说明猜猜会发生什么?
是的,会不停地循环调用。因为proxy是代理类的对象,当该对象方法被调用的时候,会触发InvocationHandler,而InvocationHandler里面又调用一次proxy里面的对象,所以会不停地循环调用。并且,proxy对应的方法是没有实现的。所以是会循环的不停报错
动态代理的原理
通过上面的讲解,相信大家对动态代理的使用理解得比较深刻了。那动态代理到底是怎么实现的呢,我们来看看源码其中关键的地方。
在newProxyInstance()发放中有这样几段。

其实大概就是把接口复制出来,通过这些接口和类加载器,拿到这个代理类cl。然后通过反射的技术复制拿到代理类的构造函数(这部分代码在Class类中的getConstructor0方法),最后通过这个构造函数new个一对象出来,同时用InvocationHandler绑定这个对象。
动态代理的使用场景
动态代理的好处我们从例子就能看出来,它比较灵活,可以在运行的时候才切入改变类的方法,而不需要预先定义它。
动态代理一般我们比较少去手写,但我们用得其实非常多。在Spring项目中用的注解,例如依赖注入的@Bean、@Autowired,事务注解@Transactional等都有用到,换言之就是Srping的AOP(切面编程)。
这种场景的使用是动态代理最佳的落地点,可以非常灵活地在某个类,某个方法,某个代码点上切入我们想要的内容,就是动态代理其中的内容。所以下一篇我们来细致了解下Spring的AOP到底是怎么使用动态代理的。
JAVA动态代理 你真的完全了解Java动态代理吗?的更多相关文章
- 你真的完全了解Java动态代理吗?看这篇就够了
之前讲了<零基础带你看Spring源码--IOC控制反转>,本来打算下一篇讲讲Srping的AOP的,但是其中会涉及到Java的动态代理,所以先单独一篇来了解下Java的动态代理到底是什么 ...
- Java事务处理全解析(六)—— 使用动态代理(Dynamic Proxy)完成事务
在本系列的上一篇文章中,我们讲到了使用Template模式进行事务管理,这固然是一种很好的方法,但是不那么完美的地方在于我们依然需要在service层中编写和事务处理相关的代码,即我们需要在servi ...
- Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架
类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader 类加载器也是Jav ...
- Java提高班(六)反射和动态代理(JDK Proxy和Cglib)
反射和动态代理放有一定的相关性,但单纯的说动态代理是由反射机制实现的,其实是不够全面不准确的,动态代理是一种功能行为,而它的实现方法有很多.要怎么理解以上这句话,请看下文. 一.反射 反射机制是 Ja ...
- 【Java核心技术】类型信息(Class对象 反射 动态代理)
1 Class对象 理解RTTI在Java中的工作原理,首先需要知道类型信息在运行时是如何表示的,这是由Class对象来完成的,它包含了与类有关的信息.Class对象就是用来创建所有“常规”对象的,J ...
- Java 代理模式(二) Java中的动态代理
动态代理类 Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类: 1.Interface InvocationHandler 该接口中仅定义了一个方法: Objec ...
- java代理(静态代理和jdk动态代理以及cglib代理)
版权声明:本文为Fighter168原创文章,未经允许不得转载. 目录(?)[+] 说到代理,脑袋中浮现一大堆代理相关的名词,代理模式,静态代理,jdk代理,cglib代理等等. 记忆特别深刻 ...
- Java EE开发平台随手记5——Mybatis动态代理接口方式的原生用法
为了说明后续的Mybatis扩展,插播一篇广告,先来简要说明一下Mybatis的一种原生用法,不过先声明:下面说的只是Mybatis的其中一种用法,如需要更深入了解Mybatis,请参考官方文档,或者 ...
- Java进阶篇设计模式之七 ----- 享元模式和代理模式
前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...
随机推荐
- js vue 页面添加水印
vue 微信页面添加水印 this.$nextTick(function() { watermark({ watermark_txt ...
- git使用和操作
git提交日志的规范 为了更规范的开发,特别是团队协同开发,对于代码托管工具的提交上都会有要求的. 作为开发者,我们一定要注重提交日志的规范性,我们要对自己写的代码负责.提交日志规范很多,最近看到了一 ...
- [C++] 空间配置器——allocator类
1.new和delete有一些灵活性上的局限:new把内存分配和对象构造组合在了一起:delete将对象析构和内存释放组合在了一起. 2.当分配一大块内存时,我们通常计划在这块内存上按需构造对象, ...
- QTP8.2--安装流程
一.安装说明: 1.进入安装文件夹,运行QTP8.2安装文件setup,进入安装向导后直接单击“QuickTest Professional 安装”选项,由于破解文件存在缺陷,所以请不要改变安装路径c ...
- 基于Linux系统--web环境搭建
上线部署文档 数据库部分1.下载Mysql服务 #yum install mysql-server 2.更改 /etc/my.cnf 3.启动Mysql ...
- 阿里云ESC服务器centos6.9使用及注意事项
阿里云ESC服务器,配置低,但是足够新手尝试操作练习. 使用之前,注意事项: 选择操作系统 设置实例快照 安装终端工具 一,选择操作系统. 可以在购买服务器的时候进行选择系统盘,也可以在购买之后在实例 ...
- 深入MYSQL随笔
(1)查询生命周期:从客户端到服务器,然后在服务器上进行解析,生成执行计划,执行,并返回给客户端.执行是整个生命周期中,最重要的阶段. (2)慢查询基础:优化数据访问,减少访问的数据行. (3)查询不 ...
- Java基础学习笔记(一) - 基础语法
1.Java程序开发过程 编译: 是指将我们编写的Java源文件翻译成JVM认识的class文件,javac编译器会检查我们所写的程序是否有错误,有错误就会提示出来,如果没有错误就会编译成功. 运行: ...
- gitbook 入门教程之从零到壹发布自己的插件
什么是插件 Gitbook 插件是扩展 Gitbook 功能的最佳方式,如果 Gitbook 没有想要的功能或者说网络上也没有现成的解决方案时,那么只剩下自食其力这条道路,让我们一起来自力更生开发插件 ...
- 4、pytest 中文文档--pytest-fixtures:明确的、模块化的和可扩展的
目录 1. fixture:作为形参使用 2. fixture:一个典型的依赖注入的实践 3. conftest.py:共享fixture实例 4. 共享测试数据 5. 作用域:在跨类的.模块的或整个 ...