最近在看rpc的实现原理,发现大部分通用的rpc框架在实现远程调用的时候,都是通过java动态代理封装好了通信细节,让用户可以像调用本地服务一样调用远程服务。但是关于java动态代理有两个问题想不通:jdk动态代理中的invoke方法是如何被自动调用的?jdk动态代理为什么只针对实现了接口的类?带着这两个问题,我仔细读了下源码。
代理的基本定义
代理模式定义:给某个原对象提供一个接口实现类(代理类),客户端不直接访问这个对象,而是通过代理类来间接访问。
代理模式涉及到了四个对象:
Client:服务调用方,通过代理类调用真实服务(serviceImpl)。
IService:功能接口类,类中包含了功能点的抽象。是serviceImpl 和 Proxy都要去实现的接口。
ServiceImpl:功能接口的具体实现类。
Proxy:代理类。其中包含了对功能时间类(ServiceImpl)的引用,从而可以操作真实服务接口。并且可以在调用真实服务处的前后进行一系列其他操作。
对象之间关系为:
代理的分类与使用
java代理主要分为静态代理和动态代理两类。
1、静态代理:所谓静态是指,在程序运行前已经写好并编译成了.class文件,而不是动态产生的。
静态代理使用方式为手动实现一个继承了IService接口类的代理类Proxy。并在Proxy代理类中手动引用ServiceImpl 功能接口的具体实现类。
代码:
package com.xiaosong.proxy.demo.service;/*** Hello world!**/
public interface IHello {public void sayHello();}

  

package com.xiaosong.proxy.demo.service.impl;import com.xiaosong.proxy.demo.service.IHello;public class Hello implements IHello {public void sayHello() {// TODO Auto-generated method stubSystem.out.println("Hello KuGou!");}
}

  

package com.xiaosong.proxy.demo.jdkproxy;import com.xiaosong.proxy.demo.service.IHello;
import com.xiaosong.proxy.demo.service.impl.Hello;public class StaticProxy implements IHello{public Hello hello;public StaticProxy (Hello hello){this.hello=hello;}public void sayHello() {System.out.println("before Hello...");hello.sayHello();System.out.println("after Hello...");}}

  

2、动态代理:所谓动态是指,不在代码编译期确定被加载的类,而是在代码运行期通过反射的方式来加载。这就是和静态编译最根本的区别。
动态代理的使用方式分为3步:
(1)写一个 InvocationHandler接口的实现类实现invoke方法,并在这个实现类中引用一个Object对象(该对象在运行期可能被赋值为各种各样的ServiceImpl 接口实现类对 
象),在invoke方法通过反射调用Object对象中的方法。
(2)调用Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this) 方法,object为1中实现类的对象,获取一个代理类Proxy。
(3)将(2)中获取到的Object对象强转为IService类,并调用IService中的方法,就可以实现对ServiceImpl 的调用了。
package com.xiaosong.proxy.demo.jdkproxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class MyInvocationHandler implements InvocationHandler {//代理目标对象public Object object;public MyInvocationHandler(Object object) {// TODO Auto-generated constructor stubthis.object=object;}//获取代理对象工具方法public Object getProxyObject(){//object.getClass().getClassLoader()确保类加载器为代理目标的加载器return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("前置方法...");//这里入参要是object,不能是proxy,否则造成死循环,后续会详细分析原因Object rs = method.invoke(object, args);System.out.println("后置方法...");return rs;}}

  

相对于静态代理,动态代理有以下几个优点:
1、动态代理的代码量不会随着接口的增加而无限制的扩大。
2、由于代理类是固定通用的,所以动态代理可以有更多的用途,比如spring AOP,比如RPC远程调用。
缺点是什么呢?
上述的静态代理和动态代理的实现都是依赖接口的,如果需要代理一个没有实现接口的方法,JDK静态代理就无计可施了。那么问题来了,为什么JDK动态代理必须是依赖接口呢?我们继续往下看。

转载于:https://www.cnblogs.com/penglaihaibiandexiaoxiami/p/8312887.html

jdk动态代理源码分析(一)---代理的定义相关推荐

  1. 动态代理及JDK动态代理源码分析

    1.为什么要动态代理 现在有这样一个需求:在聊天系统中,把每一个所说的话记录到日志文件里面,初学者可能是这样来设计 在speak方法中调用log方法,记录到数据库.这样设计有明显的不足:1.log方法 ...

  2. 动态代理源码分析,实现自己的动态代理

    什么是代理 增强一个对象的功能 买火车票,app就是一个代理,他代理了火车站,小区当中的代售窗口 java当中如何实现代理 java实现的代理的两种办法 代理的名词 代理对象 增强后的对象 目标对象 ...

  3. JDK动态代理源码解析

    分析版本jdk1.8 在分析jdk动态代理之前,先来了解java WeakReference弱引用的使用.运行期创建目标对象的代理非常耗时,使用缓存来存储生成的代理类显得尤为重要.jdk动态代理使用弱 ...

  4. 深入剖析JDK动态代理源码实现

    动态代理.静态代理优缺点 优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性.这是代理的共有优点.动态代理只有在用到被代理对象的时候才会对被代理类进行类加载. 而静态代理在编译器就已经开始占内存 ...

  5. Android动态代理源码分析

    前言 前面我们简单介绍了代理模式的使用Android设计模式详解之代理模式,我们也明白了动态代理模式的重要性,那动态代理究竟是如何实现将方法交给InvocationHandler.invoke执行的呢 ...

  6. javabean反射改字段内容_BAT程序员编写:深入理解 Java 反射和动态代理源码分析...

    什么是反射 反射(Reflection)是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. 通过反射机制,可以在运行时访问 Java ...

  7. jdk动态代理源码学习

    最近用到了java的动态代理,虽然会用,但不了解他具体是怎么实现,抽空看看了看他的源码. 说到Java的动态代理就不能不说到代理模式,动态代理也就是多了一个'动态'两字,在<大话设计模式> ...

  8. jkd动态代理源码分析

    代理对象的生成方法是: Proxy.newProxyInstance(...),进入这个方法内部,一步一步往下走会发现会调用 ProxyGenerator.generateProxyClass(),这 ...

  9. Java动态代理源码详解

    一.概述   前言:本文除了讲解JDK动态代理及CGLIB动态代理实例和应用外,还会讲解JDK动态代理源码实现过程以及自己写一手个JDK动态代理等.   动态代理在很多底层框架中都会用得到,比如在Sp ...

最新文章

  1. 在线作图|如何绘制一个好看的堆叠柱状图
  2. Windows客户机脱域问题及解决办法
  3. Django:模型model和数据库mysql(一)
  4. 【转】usermod 添加用户多个附属组
  5. html5怎么改变submit样式,html5中submit是按钮么
  6. oracle 触发器 upsert,如何使SQLAlchemy insert与Postgres多处理proof upsert触发器一起工作?...
  7. eval、json.parse()的介绍和使用注意点
  8. 在VNC远程桌面环境Xfce4中Tab键失效的解决方法
  9. 7-36 社交网络图中结点的“重要性”计算 (30 分)(思路加详解)兄弟们PTA乙级题目冲起来
  10. Linux基本操作【作业】
  11. [精华] 讨论 Setsockopt选项
  12. Tensorflow保存神经网络参数有妙招:Saver和Restore
  13. find查找文件和目录
  14. 540s inter 固件_Intel SSD Firmware Update Tool(英特尔ssd固件更新工具)下载 v2.1.6官方版...
  15. win10电脑时间同步设置方法
  16. OpenCV学习笔记(六)—— OpenCV for Android打开相机
  17. Python3环境安装配置
  18. Python:用tkinter制做一个音乐下载小软件
  19. 父视图坐标转换为子视图_简单的数学将简单的2D游戏视图转换为透视3D视图
  20. 观察者模式解读厦门建国以来最强台风

热门文章

  1. csapp学习笔记2021.1.9
  2. CPU并行与GPU并行联系及区别
  3. Matlab与C/C++混合编程 (基于Opencv库)
  4. 第一章 PX4-Pixhawk-程序编译过程解析
  5. ICPC China Nanchang National Invitational - I. Max answer(线段树+ST)
  6. 快速排序的三种实现方法
  7. ​ RROR 1221 (HY000): Incorrect usage of spatial/fulltext/hash index and explicit index orde ​
  8. 常见排序算法(C实现)
  9. python排序之sort和sorted
  10. [BUUCTF-pwn]——judgement_mna_2016