理解java动态代理
java动态代理是java语言的一项高级特性。在平时的项目开发中,可能很难遇到动态代理的案例。但是动态代理在很多框架中起着不可替代的作用,例如Spring的AOP。今天我们就聊一聊java动态代理的实现原理。
jdk对于动态代理的支持主要依赖于两个类:Proxy和InvocationHandler。我们先看一下类图。

Subject类是主题类,定义了我要做什么。我们需要代理的类即实现Subject接口的RealSubject。
1.InvocationHandler
InvocationHandler接口是jdk提供的接口,这个接口只有一个方法
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
我们先了解下InvocationHandler这个类是做什么。以下是java doc
* <p>Each proxy instance has an associated invocation handler.
* When a method is invoked on a proxy instance, the method
* invocation is encoded and dispatched to the {@code invoke}
* method of its invocation handler.
每一个代理实例都会和一个invocation handler关联,准确的说,每一个proxy类都会持有一个InvocationHandler实例,并且将目标函数交给InvcationHandler实例去执行。InvocationHandler只有invoke()这个方法,这个方法即实际被调用的方法。不管代理调用的是何种方法,处理器被调用的一定是invoke()方法。下面我们看看这个方法的参数。
1. Object proxy。传入的Subject引用,即我们想要真正执行的目标对象。
2. Method method。Method是java reflection API的一部分。这里传入的method对象,是实际被调用的method方法。
3. Object[] args。这是方法调用时传入的参数数组。
了解invoke()方法后,读者一定想知道,Subject的目标方法是怎么被调用的呢?接下来我们继续了解Proxy类。
2. Proxy
接下来我们了解下Proxy类是如何与InvocationHandler一共工作的。java doc中对Proxy的介绍如下:
* provides static methods for creating dynamic proxy
* classes and instances, and it is also the superclass of all
* dynamic proxy classes created by those methods.
Proxy提供了一个静态方法去创建动态代理类,最常用的就是下面这个方法了。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
利用newProxyInstance可以动态的创建所需要的代理对象,并且和与它关联的InvocationHandler绑定。参数如下
1. ClassLoader loader, 加载代理类的类加载器。
2. Class<?>[] interfaces, 代理类实现的接口。创建的代理类对象,只能强转为该interfaces的子类。
3. InvocationHandler h, 代理类所关联的InvocationHandler。所有被代理的方法都会通过该InvocationHandler的invoke()方法执行。
newProxyInstance方法是生成代理类的关键方法,代理类在程序运行的过程中生成,因而叫做动态代理。
3. 案例
了解了这两个最重要的类之后,我们需要通过一个实例来帮助我们更好的理解动态代理的运行机制。
首先我们创建一个Subject接口以及其实现类。
步骤1. 定义Subject
public interface Subject {
public void say(String str);
}
public class SubjectBean implements Subject {
@Override
public void say(String str) {
System.out.println(str);
}
}
Subject的say方法是我们需要代理的方法。在该方法的前后我们不妨做一些额外的操作。接下来我们定义我们的InvocationHandler。
步骤2. 定义InvocationHandler
public class MyInvocationHandle implements InvocationHandler {
Subject subject;
public MyInvocationHandle(Subject subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("pre");
method.invoke(subject, args);
System.out.println("post");
return null;
}
}
通过构造器,把被代理的对象传入。
步骤3. 定义生成代理类方法实现
public class Main {
public static Subject getProxy(Subject subject){
return (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(),
subject.getClass().getInterfaces(),
new MyInvocationHandle(subject));
}
public static void main(String[] args) {
Subject subject = new SubjectBean();
Subject proxy = getProxy(subject);
proxy.say("hello");
}
}
执行main函数,最后输出的结果为:

可见,say()函数真正method.invoke(subject, args)这里完成的。在执行前后可以加入任意代码片段,完成对say()方法的增强操作。
4. debug
我们对main方法debug看看,proxy类到底是什么。如下图

com.sun.proxy.$Proxy()类,是Proxy.newProxyInstance被调用后在jvm运行时动态生成的一个对象,命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。至于它为什么可以转为Subject,是因为我们在传入的第二个参数中,规定了它的类型信息。
这篇文章主要简述了java动态代理的实现机制。如有错误之处,还望读者多多指教。
参考文献:
《Head First设计模式》
理解java动态代理的更多相关文章
- 深入理解 Java 动态代理机制
Java 有两种代理方式,一种是静态代理,另一种是动态代理.对于静态代理,其实就是通过依赖注入,对对象进行封装,不让外部知道实现的细节.很多 API 就是通过这种形式来封装的. 代理模式结构图(图片来 ...
- 彻底理解JAVA动态代理
代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 代理模式的结构如下图所示. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public ...
- 理解Java动态代理(1)—找我还钱?我出钱要你的命
代理模式是最常用的一个设计模式之一,理解起来也是很简单,一张图足以说明了,LZ就不废话了. 至于代理模式能干嘛也不是LZ今天想说的,今天主要想简单介绍下JAVA里面的动态代理.“动”当然是相对“静”来 ...
- 深入理解java动态代理机制
动态代理其实就是java.lang.reflect.Proxy类动态的根据您指定的所有接口生成一个class byte,该class会继承Proxy类,并实现所有你指定的接口(您在参数中传入的接口数组 ...
- 轻松理解 Java 静态代理/动态代理
目录 什么是代理模式 定义 代理模式的主要角色 优点 缺点 静态代理 动态代理 JDK原生动态代理 例子 分析 小结 CGLIB动态代理 例子 分析 final类型 其他方案 尾声 理解Java动态代 ...
- JAVA动态代理基础
Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM) 彻底理解JAVA动态代理 class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中. ...
- 详解java动态代理机制以及使用场景
详解java动态代理机制以及使用场景 https://blog.csdn.net/u011784767/article/details/78281384 深入理解java动态代理的实现机制 https ...
- JAVA动态代理的全面深层理解
Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过 ...
- JAVA动态代理模式(从现实生活角度理解代码原理)
所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...
随机推荐
- Css三栏布局自适应实现几种方法
Css三栏布局自适应实现几种方法 自适应实现方法我们可以从三个方法来做,一个是绝对定位 ,自身浮动法 和margin负值法了,下面我们一起来看看这三个例子吧,希望例子能帮助到各位同学. 绝对定位法三栏 ...
- 在项目中使用JMail发送邮件
1.添加JMail组件:在vs的解决方案资源管理器中,右键添加引用,选择浏览,选择jmail.dll文件,在Bin文件夹中就可以看到添加的JMail组件. 2.注册JMail组件:开始-->运行 ...
- MyBatis 最强大的特性之一就是它的动态语句功能
MyBatis 最强大的特性之一就是它的动态语句功能.如果您以前有使用JDBC或者类似框架的经历,您就会明白把SQL语句条件连接在一起是多么的痛苦,要确保不能忘记空格或者不要在columns列后面省略 ...
- Hibernate Annotations 注解
Hibernate Annotations 注解 对于org.hibernate.annotations与org.hibernate.persistence,它的注释比如Columns,可是不知道怎么 ...
- Merging an upstream repository into your fork
1. Check out the branch you wish to merge to. Usually, you will merge into master. $ git checkout ma ...
- 【cb2】扩展硬盘
1.硬盘为sata串口 2.参考 http://docs.cubieboard.org/tutorials/ct1/installation/moving_rootfs_from_nandflash_ ...
- Objective-C Runtime初探:self super
题目 上题目,已知A是爷爷,B是爸爸,C是孙子. @interface A : NSObject - (void)f; @end @interface B : A - (void)f; - (void ...
- MathType中怎么设置字体默认颜色
MathType功能非常强大,在编辑公式时使用非常方便.利用MathType破解版不仅可以改变公式的字体和字号,也可以改变公式字体颜色.有时在编辑完成后需要对MathType公式格式全部进行修改,这时 ...
- 使用binlog日志还原数据详解
1)看一下你的mysql服务器有没开启binlog日志(ON为开启,OFF为未开启) show variables like 'log_bin'; 2)找到你的binlog文件在哪 登录 mysql ...
- ios浅谈关于nil和 NIL区别及相关问题
本文转载至:http://blog.csdn.net/guozh/article/details/8469131 1.nil和null从字面意思来理解比较简单,nil是一个对象,而NULL是一个值,我 ...