你真的完全了解Java动态代理吗?看这篇就够了

之前讲了《零基础带你看Spring源码——IOC控制反转》,本来打算下一篇讲讲Srping的AOP的,但是其中会涉及到Java的动态代理,所以先单独一篇来了解下Java的动态代理到底是什么,Java是怎么实现它的。

动态代理看起来好像是个什么高大上的名词,但其实并没有那么复杂,直接从字面就很容易理解。动态地代理,可以猜测一下它的含义,在运行时动态地对某些东西代理,代理它做了其他事情。先不去搞清楚这个动态代理真正的含义,我们来举个生动的例子来理解下它到底做了什么。

一个例子

一个程序员Developer,他会开发code,他调试debug。

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

但是呢,有个叫Zack的程序员它在开发之前,会祈祷一下,这样他开发的代码就不会有bug。

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到底是怎么使用动态代理的。



更多技术文章、精彩干货,请关注
博客:zackku.com
微信公众号:Zack说码

原文地址:http://blog.51cto.com/14073604/2320387

时间: 2024-08-15 18:23:23

你真的完全了解Java动态代理吗?看这篇就够了的相关文章

好程序员Java教程Java动态代理机制详解

好程序员Java教程Java动态代理机制详解:在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的.首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的: InvocationHandler: 1InvocationHandler is the interface implemented by the invocation handle

Java动态代理 深度详解

代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 今天我将用非常简单易懂的例子向大家介绍动态代理的两种类型,接着重点介绍动态代理的两种实现方式(Java 动态代理和 CGLib 动态代理),最后深入剖析这两种实现方式的异同,最后说说动态代理在我们周边框架中的应用. 在开始之前,我们先假设这样一个场景:有一个蛋糕店,它们都是使用蛋糕机来做蛋糕的,而且不同种类的蛋糕

理解java动态代理

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

java动态代理的实现

动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程. 友情提示:本文略有难度,读者需具备代理模式相关基础知识,. 通常情况下,代理模式中的每一个代理类在编译之后都会生成一个class文件,代理类所实现的接口和所代理的方法都被固定,这种代理被称之为静态代理(Static Proxy).那么有没有一种机制能够让系统在运行时动态创建代理类?答案就是本文将要介绍的动态代理(Dynamic Proxy).动态代理是一种较

java动态代理机制

首先了解代理设计模式,其思想是为其他对象提供一种代理以控制对这个对象的访问. java动态代理就是遵循这种思想,spring中的AOP实现原理就是java的动态代理. 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的. 每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通

java动态代理

要想了解Java动态代理,首先要了解什么叫做代理,熟悉设计模式的朋友一定知道在Gof总结的23种设计模式中,有一种叫做代理(Proxy)的对象结构型模式,动态代理中的代理,指的就是这种设计模式. 在我看来所谓的代理模式,和23种设计模式中的"装饰模式"是一个东西.23种设计模式中将它们作为两种模式,网上也有些文章讲这两种模式的异同,从细节来看,确实可以人为地区分这两种模式,但是抽象到一定高度后,我认为这两种模式是完全一样的.因此学会了代理模式,也就同时掌握了装饰模式. 代理模式 代理模

java 动态代理示例,带主要注释

Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interface Subject { String hello(String name); void say();} 接口实现: public class ImpSubject implements Subject { @Override public String hello(String name){ r

java动态代理原理及解析

代理:设计模式 代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 通过代理层这一中间层,有效的控制对于真实委托类对象的直接访问,同时可以实现自定义的控制策略(Spring的AOP机制),设计上获得更大的灵活性. java动态代理的类和接口(jdk1.6源码) 1,java.lang.reflect.Proxy:动态代理机制的主类,提供一组静态方法为一组接口动态的生成对

彻底理解JAVA动态代理

注:本文转自 http://www.cnblogs.com/flyoung2008/archive/2013/08/11/3251148.html 代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 代理模式的结构如下图所示. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Subject { public void doSomething(); } public class RealSubject i