在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. Swift 2.0 字符串学习笔记(建议掌握OC字符串知识的翻阅)

    自己公司开现在使用OC语言在写,但Swift似乎是苹果更推荐使用的开发语言,估计也是未来开发的趋势,自己以前有接触swift,但又由于公司的项目赶,也没有时间去好好地学习这款开发语言.现在年底了,项目 ...

  2. BZOJ 2463: [中山市选2009]谁能赢呢?(博弈论)

    好吧我能说这道题我是猜过去的么= =,看到只有一个数x,x=2时alice赢,就猜奇数bob赢,偶数alice赢,然后就稀里糊涂过了= = 后来找了http://www.haogongju.net/a ...

  3. 卷积神经网络(CNN)模型结构

    在前面我们讲述了DNN的模型与前向反向传播算法.而在DNN大类中,卷积神经网络(Convolutional Neural Networks,以下简称CNN)是最为成功的DNN特例之一.CNN广泛的应用 ...

  4. Cloud9vue&vux上传github小步骤

    成功后创建出以下文件,再输入: git init 再输入:$ git remote add origin https://github.com/github用户名/vux1 然后:git add. 按 ...

  5. Alamofire源码解读系列(五)之结果封装(Result)

    本篇讲解Result的封装 前言 有时候,我们会根据现实中的事物来对程序中的某个业务关系进行抽象,这句话很难理解.在Alamofire中,使用Response来描述请求后的结果.我们都知道Alamof ...

  6. thinkphp apicloud 下拉刷新 。。。由于新人里面导入了vue.js

    //刷新 apiready = function(){ var count; var i= 1; var param = {}; toDoRequest(); param.loadingImgae = ...

  7. vs2017 .net core WebApp 去掉ApplicationInsights

    vs2017新建的 .net core WebApp都内置了这个遥测中间件进去,嗯,用AZURE的话是不错能无缝支持.但不用AZURE就没什么用了. 为了不占地方和提高一点点初始启动的速度,对新建的项 ...

  8. 深究WeixinJSBridge未定义之因

    对于一个没有使用微信JS-SDK的网站来说,我们竟然收到了WeixinJSBridge is not defined 的报错: 去网上一搜,发现很多开发者都遇到类似的问题: 我的微信项目,没有用到微信 ...

  9. 69个微信小程序常见问题

    本文转自 遇到小程序方面的问题,该去哪里提问呢? 若是能得到微信官方的解答,想必是最叫人安心的.而微信也确实提供了这么一个地方. 在微信公众平台的开发者社区,就置顶了一个「小程序常见问题 FAQ」帖. ...

  10. 3301: [USACO2011 Feb] Cow Line

    3301: [USACO2011 Feb] Cow Line Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 82  Solved: 49[Submit ...