JDK动态代理底层实现原理 jdk动态代理的实现原理

代理模式是Java常见的设计模式之一 。所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象 。
JDK代理模式就是让处理业务类专心处理核心业务,一些可以抽取出的冗余代码交给代理处理。无论是动态代理还是静态代理 ,要代理某类 都要与委托类(真实实现类)实现同一接口,并且代理包含(注入)某类实例进行业务处理,和代理的外加服务(日志、事物等等)可以叫做:业务增强 。
在现实生活中,这种情形非常的常见,比如请一个律师代理来打官司


JDK动态代理底层实现原理 jdk动态代理的实现原理

文章插图
JDK代理模式最大的特点就是代理类和实际业务类实现同一个接口(或继承同一父类),代理对象持有一个实际对象的引用,外部调用时操作的是代理对象,而在代理对象的内部实现中又会去调用实际对象的操作(代理两要素:共同实现和引用)
代理模式的实现
代理模式可以有两种实现的方式,一种是静态代理类,另一种是各大框架都喜欢的动态代理 。
静态代理
我们先看针对上面图中实现的例子,再看静态代理的特点 。
Movie 接口的实现
public interface Movie {void player();}
实现了Movie 接口的 真实 实现类(委托类):
public class RealMovie implements Movie {@Overridepublic void player() {System.out.println(">>>>>>>> 您正在观看《东科1903·奋斗史》");}}
实现了Movie 接口的 代理 实现类:
public class Cinema implements Movie {RealMovie realMovie;public Cinema(RealMovie realmovie) {this.realMovie = realmovie;}public void player() {System.out.println("|||||||||||||||||||||||电影开始前,卖爆米花");realMovie.player();System.out.println("----------------------电影结束了,打扫卫生");}}
具体的调用如下:
public class ProxyTest {public static void main(String[] args) {//*****************静态代理方式Cinema cinema = new Cinema(new RealMovie());cinema.player();}}
使用静态代理的好处:
使得真实角色处理的业务更加纯粹,不再去关注一些公共的事情 。
公共的业务由代理来完成---实现业务的分工 。
公共业务发生扩展时变得更加集中和方便 。
缺点:每一个代理类都必须实现一遍真实 实现类(也就是realMovie)的接口,如果接口增加方法,则代理类也必须跟着修改 。其次,每一个代理类对应一个真实实现类(委托类),如果真实实现(委托类)非常多,则静态代理类就非常臃肿,难以胜任
动态代理
动态代理有别于静态代理,是根据代理的对象,动态创建代理类 。这样,就可以避免静态代理中代理类接口过多的问题 。动态代理是通过反射来实现的,借助Java自带的java.lang.reflect.Proxy,通过固定的规则生成 。
其步骤如下:
  1. 编写一个委托类的父接口,即静态代理的(Movie接口)
  2. 实现一个真正的委托类,即静态代理的(RealMovie类)
  3. 创建一个动态代理处理器,实现InvocationHandler接口,并重写该invoke方法
  4. 在测试类中,生成动态代理的对象 。
第一二步骤,和静态代理一样,不过说了 。第三步,代码如下:
/** * 动态代理类/ 调用处理器(执行核心业务,并 业务增强) */public class MyInvocationHandler implements InvocationHandler {Object object;public MyInvocationHandler (Object object){this.object = object;}/*** @param proxy 自动生成后的 代理对象* @param method 代理对象调用的方法* @param args 调用的方法中的参数* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("|||||||||||||||||||||||电影开始前,卖爆米花");method.invoke(object,args);System.out.println("----------------------电影结束了,打扫卫生");return null;}}
第四步,创建动态代理的对象
public class ProxyTest {public static void main(String[] args) {//真实实现(委托类)RealMovie realmovie = new RealMovie();//*****************动态代理方式MyInvocationHandler cinemaInvocation = new MyInvocationHandler (realmovie);//loader 自然是类加载器;interfaces 代码要用来代理的类的父接口;h 一个 InvocationHandler 对象Movie movie = (Movie) Proxy.newProxyInstance(Movie.class.getClassLoader(),new Class[]{Movie.class},cinemaInvocation);movie.player();}}
创建动态代理的对象,需要借助Proxy.newProxyInstance 。该方法的三个参数分别是: