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

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

下面说说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. New Concept English 1-10

    Lesson 10 The loss of Titanic The great ship, Titanic, sailed for New York from Southampton on April ...

  2. CSS颜色代码

    颜色值 CSS 颜色使用组合了红绿蓝颜色值 (RGB) 的十六进制 (hex) 表示法进行定义.对光源进行设置的最低值可以是 0(十六进制 00).最高值是 255(十六进制 FF).从 0 到 25 ...

  3. ISO学习中代码截图

    自定义插件 1.使用时的调用方法 导入头文件,创建对象,设置尺寸,传入数据: 2,内部方法的实现 XMGPageView.m XMGPageView.h XMGPageView.xib 注意点 自定义 ...

  4. json,pickle

    json  将python基本数据类型转换成字符串形式 import json dict = {'k1':'v1'} result = json.dumps(dict) print(result,ty ...

  5. 关于 K米 —— 的案例分析

    第一部分 调研,评测 评测 下载并使用,描述最简单直观的个人第一次上手体验. 我觉得ktv遥控软件设计的很好,给我带来了很多方便,点歌也不用那么麻烦了跑到台子那里点,调各种音量灯光也是,所以第一次上手 ...

  6. mysql 修改密码

    安装完成后,默认本地登录超级管理员root,密码为空连接服务后(先停止服务,在wamp中运行mysql控制台enterpass:直接回车),执行set password for root@localh ...

  7. 关于webrtc视频会议的解决方案

    以我的经验来看视频会议分两种模式:网状模型,星型 1.网状模型 所谓的网状模型就是参加会议的人中每两个人建立一个点对点的连接. 比如:一个会议室有三个人A,B,C 基于网络模型就需要这样: 1.A和B ...

  8. unity3d 第三人称视角的人物移动以及相机控制

    何谓第三人称?就像这样: 用wasd控制人物移动,同时保持在相机的中心.用鼠标右键与滚轮控制相机的角度和距离. 先说一下人物的移动: 首先给作为主角的单位加上 Charactor Controller ...

  9. tomcat7 日志设置为log4j

    tomcat的日志设置用log4j的官方文档:http://tomcat.apache.org/tomcat-7.0-doc/logging.html 1. 下载tomcat-juli.jar, to ...

  10. Jquery中each的三种遍历方法

    Jquery中each的三种遍历方法 $.post("urladdr", { "data" : "data" }, function(dat ...