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-数据交互--AJAX
一:介绍 今天跟下大家简单的介绍一下,在前端开发中,前后端数据交互的一种手段,我们都知道,在前端往后端传送数据的话,利用get,post方法即可向后端发送数据,后端将数据接受,链接到数据库,进行数据库 ...
- Spark学习之Scala的基础知识
Scala的变量声明 在Scala创建变量的时候,必须使用val或者var val,变量值不可修改,一旦分配不能重新指向别的值 var,分配后,可重新指向类型相同的值 举例 val lines = s ...
- 浏览器兼容性知识&测试计划&测试报告
浏览器兼容性知识&测试计划&测试报告 浏览器兼容性问题:网页或网站兼容性问题,因为不同浏览器使用内核及所支持的HTML(标准通用标记语言下的一个应用)等网页语言标准不同:以及用户客户端 ...
- TCP/IP 物理层卷一 -- 基本概念
一.基本概念: 物理层:TCP/IP 协议簇的最底层,物理层所需要考虑的是如何在连接计算机的传输媒体上传输数据的比特流,而不是连接计算机的具体物理设备. 信号:数据的电气或电磁表现,是数据在传输媒体上 ...
- linux 进程消耗查看
Linux下如何查看哪些进程占用的CPU内存资源最多 linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合: ps aux|head -1;ps aux|grep -v PID|sor ...
- impala对元数据的界面更新操作
执行 impala-shell 即能进入界面操作sql.如果在hive更新了数据之后,而在impala中却无法看到更新后的数据的话,意味着impala里元数据信息还没有刷新,此时在impala操作界面 ...
- 【django】分页
分页 1.简单分页 from django.conf.urls import url from django.contrib import admin from app01 import views ...
- uni-app实现滑动切换效果
在对于uni-app框架了解之后,今天就实现一个滚动切换tab效果,这个很常见的一个效果,最后封装成一个组件,便于以后使用,写这个需要引入uni官方提供的uni.css样式,用到了写好的样式,就不需要 ...
- Android 禁止Edittext弹出系统软键盘 的几种方法
第一种方法:在XML文件下添加: android:focusable="true" android:focusableInTouchMode="true" 第二 ...
- C语言I博客作业02
这个作业属于那个课程 C语言程序设计I 这个作业要求在哪 https://edu.cnblogs.com/campus/zswxy/CST2019-3/homework/8656 我在这个课程的目标 ...