在Java的动态代理机制中,有两个重要的类。一个是InvocationHandler,另一个是Proxy。

  • InvocationHandler:每一个动态代理类都必须要实现InvocationHandler接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。

    /**
    *
    * @param proxy 代理的真实对象
    * @param method 调用真实对象的某个方法的method对象
    * @param args 调用方法时传的参数
    * @return 调用结果
    * @throws Throwable
    */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}
  • Proxy:动态的创建一个代理对象的类,我们用的比较多的就是newProxyInstance这个方法。

     /**
    *
    * @param loader ClassLoader对象,由哪个ClassLoader对象来对生成的代理对象进行加载
    * @param interfaces Interface对象数组,提供一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这个我们就能调用这组接口中的方法了
    * @param h InvocationHandler对象,当这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
    */
    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {}
  • Demo

    Subject接口

    public interface Subject {
    void say(String str);
    }

    RealSubject类

    public class RealSubject implements Subject {
    @Override
    public void say(String str) {
    System.out.println("hello , " + str);
    }
    }

    动态代理类

    public class DynamicProxy implements InvocationHandler {
    
        // 要代理的真实对象
    private Object target; // 给代理的真实对象赋初始值
    public DynamicProxy(Object target) {
    this.target = target;
    } @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    before();
    // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
    method.invoke(target, args);
    after();
    return null;
    } public void before() {
    System.out.println("before...");
    } public void after() {
    System.out.println("after...");
    }
    }

    Client类

    public class Client {
    public static void main(String[] args) {
    Subject realSubject = new RealSubject();
    // 将要代理的真实对象传进去,最后是通过该真实对象来调用其方法的
    InvocationHandler handler = new DynamicProxy(realSubject);
    // 通过Proxy来创建对象
    Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);
    System.out.println(subject.getClass().getName());
    subject.say("webb");
    }
    }

    输出结果

    com.sun.proxy.$Proxy0
    before...
    hello , webb
    after...

    我们看到subject.getClass().getName()看到打印出来的是 $Proxy0,首先解释下为什么这里可以将其转换为Subject类型的对象?原因就是在newProxyInstance这个方法的第二个参数上,我们给这个代理对象提供了一组什么接口,那么这个代理对象就会实现这种组接口,这个时候我们可以将这个代理对象强制类型转化为这组接口中的任意一个,因为这里的接口是Subject类型,所以就可以将它转化为Subject类型。同时我们一定要记住,通过Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。

    当我们执行subject.say("webb");的时候,会自动跳转到由这个代理对象关联到的handler中的invoke方法去执行,而handler对象又接受了一个RealSubject类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用handler中的invoke方法去执行。

参考文章:

1.https://my.oschina.net/huangyong/blog/159788?p=5&temp=1490924411201#blog-comments-list

2.http://www.cnblogs.com/xiaoluo501395377/p/3383130.html

【Java基础】 Java动态代理机制的更多相关文章

  1. java中的动态代理机制

    java中的动态代理机制 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现 ...

  2. Java 反射 设计模式 动态代理机制详解 [ 转载 ]

    Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...

  3. 深度剖析java中JDK动态代理机制

    https://www.jb51.net/article/110342.htm 本篇文章主要介绍了深度剖析java中JDK动态代理机制 ,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定 ...

  4. Java进阶 | Proxy动态代理机制详解

    一.Jvm加载对象 在说Java动态代理之前,还是要说一下Jvm加载对象的过程,这个依旧是理解动态代理的基础性原理: Java类即源代码程序.java类型文件,经过编译器编译之后就被转换成字节代码.c ...

  5. Java基础-CGLIB动态代理

    JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继 ...

  6. Java基础-JDK动态代理

    JDK的动态代理依靠接口实现  代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代 ...

  7. Java基础加强——动态代理

    代理模式: 为其他对象提供一种代理以控制对这个对象的访问. 代理模式主要分为两类: 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了.  ...

  8. Java基础-jdk动态代理与cglib动态代理区别

    JDK动态代理 此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑. 代理模式在实际使用时需要指定具体的目标对象 ...

  9. 重学JAVA基础(三):动态代理

    1.接口 public interface Hello { public void sayHello(); } 2.实例类 public class Hello2 { public void sayH ...

  10. Java 动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

随机推荐

  1. 安卓TCP通信版本2

    PC做服务器,安卓做客户端. 安卓获取输入框的内容并发送,然后等待接收服务器的消息 服务器先行开启,接收到客户端的数据,然后回复消息. 实现了对线程类的封装,通过按钮启动线程发送并接收 服务器代码(j ...

  2. 张高兴的 UWP 开发笔记:用 Thumb 控件仿制一个可拖动 Button

    在 WPF 上可用的控件拖动方法在 UWP 上大多没用,那干脆用 Thumb 仿制一个吧. 关于 Thumb 控件的教程也不多,毕竟在 WPF 控件拖动有很多种方法, Thumb 就显得很鸡肋了.下面 ...

  3. html5中的meta标签

    1. <meta http-equiv="X-UA-Compatible" content="IE=edge" /> IE=edge告诉IE使用最新 ...

  4. Java之路——名词解释(一)

    一.开篇 许多人在初接触Java的时候,都会被各种Java的英文缩写名词给弄得头晕脑胀.看一个技术,内容里又会有一堆其他的技术名词,看了半天不知所云.尝试去查一下这些名词的解释,除了非常学术性的解释之 ...

  5. awk,sed文本处理案例

    #!/bin/bash ############################################################################# #针对一个多级目录下 ...

  6. 原生javascript满屏上下滚动

    使用到一个滚动事件:onmousewheel  (不支持火狐浏览器)   /  DOMMouseScroll  (支持火狐浏览器):这篇代码支持ie8以上版本,Firefox,Safari,Chrom ...

  7. 一次MySQL死锁问题解决

    一次MySQL死锁问题解决 一.环境 CentOS, MySQL 5.6.21-70, JPA 问题场景:系统有定时批量更新数据状态操作,每次更新上千条记录,表中总记录数约为500W左右. 二.错误日 ...

  8. InstallShield打包

    使用2010部分汉化版(2010之后找不到更新的破解版本),主要用于打包桌面应用程序. 主要步骤: 1.3种主要的工程类型: Basic MSI,安装脚本不易使用. InstallScript,无法加 ...

  9. 规范 : loading display & ui-view loading

    angular 没有compile 完成的接口,最像的接口是$viewContentLoaded(router ui),但是一开始会开始跑,因为有ui-view 暂时解决方法是在body的loadin ...

  10. 关于fibonacci数列用JS写的一点小优化

    直接上代码 var month = prompt("请输入月数:") function fibobo(x) { //先定义一个已有前两项的数组,用来作缓存 var arr = [1 ...