所谓代理,其实就是相当于一个中间人,当客户端需要服务端的服务时,不是客户直接去找服务,而是客户先去找代理,告诉代理需要什么服务,然后代理再去服务端找服务,最后将结果返回给客户。

在日常生活中,就拿买火车票来比喻。以前买票,都是需要到火车站去买的,但是有些人距离火车站太远不方便去,来来回回总是很麻烦。于是铁道部就在城市的各个地方增设一个火车票代售点,在这个代售点就可以买票而不用去火车站了。这里,这个代售点就相当于一个代理,可以提供火车站所提供的服务。

下面说说JAVA中的代理

代理的实现又分为静态代理和动态代理,

一.静态代理

静态代理意思就是静态的,不能改变的,客户,服务,代理这三者是已经决定好了的。它的实现需要一个接口和这个接口的实现类。

这个接口就是服务端所提供的服务。

比如下面的代码:

//服务
interface Station{
void sellTickit();
} //服务提供类
class SubStation implements Station{
public void sellTickit(){
System.out.println("卖火车票总站");
}
} //服务代理类
class ProxyStation implements Station{ private Station station = null; public ProxyStation(Station station){
this.station = station;
} public void sellTickit(){
System.out.println("这里是代售点,需要去总站拿票");
station.sellTickit();
System.out.println("已经从总站拿到票"); }
} public class ProxyTest{
//此处调用就相当于客户端
public void static main(String[] args){
Station station = new ProxyStation(new SubStation());
station.sellTickit();
}
} //输出结果:
//这里是代售点,需要去总站拿票
//卖火车票总站
//已经从总站拿到票

从上面代码可以看到,当用户调用sellTickit服务时,并不是直接调用服务类的sellTickit,而是调用代理类的sellTickit,代理类中sellTickit再去调用服务类的方sellTickit来提供服务的。这样,代理类就可以在实际调用服务类的服务时做更多的事情,也可以向客户端屏蔽服务类提供服务的细节。

这就是静态代理,虽然说实现起来比较简单,但是从简单的问题上更容易看清楚本质。代理的本质其实就是代理向客户端屏蔽服务端,并且向客户端提供服务端的部分服务

还是拿上面卖票的例子来说,目前服务提供类只提供了卖票服务,所以代理中也只提供了卖票服务。如果现在,服务提供类增加了退票、改签等服务,那么在代理中,就应该也增加这些服务(当然也可以不增加,这样客户就直接去总站退、改,这里假设代理会提供所有的服务)。理解了代理的本质,再来看看动态代理。

二.动态代理

动态代理的实现又分为JDK动态代理和CGLIB动态代理,这里先只说JDK动态代理。动态就是相对于静态的,代理类并不是一开始就有的,而是动态生成的。

此动态代理同样需要一个接口和此接口的实现类,看如下代码

//服务
interface Station{
void sellTickit();
} //服务提供类
class SubStation implements Station{
public void sellTickit(){
System.out.println("卖火车票总站");
}
} class MyInvocationHandler implements InvocationHandler{ Object target = null;
public MyInvocationHandler(Object obj){
this.target = obj;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("这里是代售点,需要去总站拿票");
Object result = method.invoke(target, args);
System.out.println("已经从总站拿到票");
return result;
}
} public class ProxyTest {
public static void main(String[] args){
SubStation subStation = new SubStation();
Station proxyStation = (Subject) Proxy.newProxyInstance(subStation .getClass().getClassLoader(),
subStation .getClass().getInterfaces(),
new MyInvocationHandler(subStation ));
proxyStation.sellTickit();
}
}

可以看到,原来静态定义的代理类已经没有,产生代理类是使用了Proxy.newProxyInstance方法,此方法接收的三个参数分别为服务提供类的类加载器,服务器提供类的接口和一个代理方法调用处理类

这样看着并不能很好的理解到底发生了什么事情,那么我就在main中的proxyStation.sellTickit()处增加断点来调试。



可以看到,此时proxyStation的值为$Proxy0,这就是动态生成的代理类。其中还是成员变量h,它就是MyInvocationHandler的实例,h.target就是SubStation的实例。

那么如何看到$Proxy0代理类的内容呢?可以参考这边文章,通过反编译出Java代码,我们可以看到动态代理所产生的代理类也很类似静态代理中的代理类,只不过是动态生成的。可以看到$Proxy0中实现了服务接口中的所有方法,在它的方法中,是通过调用MyInvocationHandler.invoke来调用服务提供类的服务的。

MyInvocationHandler.invoke方法中的三个参数: proxy, method, args分别代表了$Proxy0的实例,调用的方法和方法的参数。

Java中的JDK动态代理的更多相关文章

  1. Spring中的JDK动态代理

    Spring中的JDK动态代理 在JDK1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.在Sun刚推出动态代理时,还很难想象它有多大的实际用途,现在动态代理是实现AOP的绝好底层 ...

  2. Java学习笔记--JDK动态代理

    1.JDK动态代理     JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和 ...

  3. Java设计模式之JDK动态代理原理

    动态代理核心源码实现public Object getProxy() { //jdk 动态代理的使用方式 return Proxy.newProxyInstance( this.getClass(). ...

  4. Java 反射之JDK动态代理

    Proxy提供用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类.如果我们在程序中为一个或多个接口动态地生成实现类,就可以使用Proxy来创建动态代理类:如果需要为一个或多个接口动态的 ...

  5. java jdk动态代理模式举例浅析

    代理模式概述 代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色. java中常用的动态代理模式为jdk动态代理和c ...

  6. 静态代理与JDK动态代理

    demo地址: https://github.com/ZbLeaning/leaning 代理: 为其他对象提供一种代理以控制对这个对象的访问.分为静态代理和动态代理.代理模式的目的就是为真实业务对象 ...

  7. 017 Java中的静态代理、JDK动态代理、cglib动态代理

    一.静态代理 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由业务实现类.业务代理类两部分组成.业务实现类负责实现主要的业务方法,业 ...

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

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

  9. Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理

    Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理 JDK动态代理的实现及原理 作者:二青 邮箱:xtfggef@gmail.com     微博:http://weibo.com/xtfg ...

随机推荐

  1. java的异常

    下面是我对Java异常知识的几个小总结,也算是资源回收一下 一.Java异常的知识 异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的.比如说,你的代码少了一个分号,那么运 ...

  2. Linux中的命令 make -f 是什么意思

    出处:http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380146d96864968d4e414c422460 ...

  3. ps一些图片的操作

    ctrl+c 复制 ctrl+n 新建 ctrl+v粘贴 ctrl+s 保存 如果要将某个带字的背景去掉它的字体那么就是 ctrl+t

  4. Bash:-3次错误输入退出脚本

    Limit_Condition() { let count++ ]];then echo "超过3次机会,自动关停脚本" exit fi Comfirm() { count= wh ...

  5. sql 查询表中所有字段的名称

    最近工作用到SQL语句查询表中所有字段的名称,网上查询,发现不同数据库的查询方法不同,例如: SQL server 查询表的所有字段名称:Select name from syscolumns Whe ...

  6. 快速增加sql数据

    declare @i int begin insert into dbo.w10test(Name) select Name from dbo.w10test end;

  7. Jquery 下实现 图片大图预览效果

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  8. easyui DataGrid 工具类之 util js

    var jq;                var tab;                var tabsIndex;                                /**     ...

  9. BCP 导出导入数据(SQL Server)

    BCP指令工具可通过安装SQL Server获得. 1. 根据现有的数据库生成表的format文件(导入导出数据的时候需要) bcp db_test.dbo.Table1 format nul -c ...

  10. 自适应css 框架 PURE

    Bootstrap 好用 但是太大啦 有时候只需要用到媒体查询这一块的样式 Pure.css可以很好地替代 直接上地址咯: http://purecss.io/ https://unpkg.com/p ...