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

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

下面说说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. 关于ES6的 模块功能 Module 中export import的用法和注意之处

    export default 的用法 export default命令用于指定模块的默认输出.显然,一个模块只能有一个默认输出,因此export deault命令只能使用一次.所以,import命令后 ...

  2. CSS盒子模型元素实际宽度的计算

    一旦为页面设置了恰当的 DTD,大多数浏览器都会按照上面的图示来呈现内容.然而 IE 5 和 6 的呈现却是不正确的.根据 W3C 的规范,元素内容占据的空间是由 width 属性设置的,而内容周围的 ...

  3. Sql server 2008镜像配置步骤

    下面主要是2008 MSSQL的一个镜像安装步骤,使用到的工具是mssql自带的Management Studio purpose : SQL SERVER 2008 mirror configura ...

  4. 通过cygwin安装openSSH

    openSSH的安装是学习hadoop必不可少的一步,如果ssh装不好,hadoop的安装会进行不下去.本人初学hadoop时发现以前安装ssh走了一些弯路,现在又有了一些认识,所以重写了这篇日志,供 ...

  5. Apache Commons CLI官方文档翻译 —— 快速构建命令行启动模式

    昨天通过几个小程序以及Hangout源码学习了CLI的基本使用,今天就来尝试翻译一下CLI的官方使用手册. 下面将会通过几个部分简单的介绍CLI在应用中的使用场景. 昨天已经联系过几个基本的命令行参数 ...

  6. dm9000c 移值新内核 linux-4.1.24

    错误 1 /home/dm9000/dm9dev9000c.c:309: error: conflicting types for 'phy_read'include/linux/phy.h:637: ...

  7. Weblogic的架构

    WebLogic管理控制台  WebLogic服务器提供了一个健壮的基于Web 的工具——管理控制台,它是执行上述任务的主要工具.通过管理控制台,你可以访问WebLogic管理服务.管理服务实现了 S ...

  8. PLSQL Developer导入Excel数据

    LSQL Developer导入Excel数据 最近处理将Excel数据导入Oracle的工作比较多.之前都是采用Sqlldr命令行导入的方式处理.每次导入不同格式的Excel表数据,都需要先把Exc ...

  9. Linux_scp

    scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器 ...

  10. Newtonsoft.Json

    在线生成实体:http://tool.chinaz.com/tools/json2entity.aspx RootObject ac = new RootObject(); ac = JsonConv ...