Java中的JDK动态代理
所谓代理,其实就是相当于一个中间人,当客户端需要服务端的服务时,不是客户直接去找服务,而是客户先去找代理,告诉代理需要什么服务,然后代理再去服务端找服务,最后将结果返回给客户。
在日常生活中,就拿买火车票来比喻。以前买票,都是需要到火车站去买的,但是有些人距离火车站太远不方便去,来来回回总是很麻烦。于是铁道部就在城市的各个地方增设一个火车票代售点,在这个代售点就可以买票而不用去火车站了。这里,这个代售点就相当于一个代理,可以提供火车站所提供的服务。
下面说说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动态代理的更多相关文章
- Spring中的JDK动态代理
Spring中的JDK动态代理 在JDK1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.在Sun刚推出动态代理时,还很难想象它有多大的实际用途,现在动态代理是实现AOP的绝好底层 ...
- Java学习笔记--JDK动态代理
1.JDK动态代理 JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和 ...
- Java设计模式之JDK动态代理原理
动态代理核心源码实现public Object getProxy() { //jdk 动态代理的使用方式 return Proxy.newProxyInstance( this.getClass(). ...
- Java 反射之JDK动态代理
Proxy提供用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类.如果我们在程序中为一个或多个接口动态地生成实现类,就可以使用Proxy来创建动态代理类:如果需要为一个或多个接口动态的 ...
- java jdk动态代理模式举例浅析
代理模式概述 代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色. java中常用的动态代理模式为jdk动态代理和c ...
- 静态代理与JDK动态代理
demo地址: https://github.com/ZbLeaning/leaning 代理: 为其他对象提供一种代理以控制对这个对象的访问.分为静态代理和动态代理.代理模式的目的就是为真实业务对象 ...
- 017 Java中的静态代理、JDK动态代理、cglib动态代理
一.静态代理 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由业务实现类.业务代理类两部分组成.业务实现类负责实现主要的业务方法,业 ...
- 深度剖析java中JDK动态代理机制
https://www.jb51.net/article/110342.htm 本篇文章主要介绍了深度剖析java中JDK动态代理机制 ,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定 ...
- Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理
Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理 JDK动态代理的实现及原理 作者:二青 邮箱:xtfggef@gmail.com 微博:http://weibo.com/xtfg ...
随机推荐
- diff输出格式解析
1 命令格式 $diff <变动之前的文件> <变动之后的文件> 2 diff文件的三种格式 normal diff context diff unified diff 3 示 ...
- Python字符串格式化
一.使用格式化符来格式化字符串: Python支持的所有格式化符 格式化符 意义 'd' 返回要格式化对象的十进制表示,如果可以 'i' 返回要格式化对象的十进制表示,如果可以 'o' 返回要格式化对 ...
- CSS中隐藏内容的3种方法及属性值
CSS中隐藏内容的3种方法及属性值 (2011-02-11 13:33:59) 在制作网页时,隐藏内容也是一种比较常用的手法,它的作用一般有:隐藏文本/图片.隐藏链接.隐藏超出范围的内容.隐藏弹出 ...
- mybatis教程
http://www.yihaomen.com/article/java/302.htm
- 关于在linux中使用图形界面的网络管理工具
有好几种自动设置的工具可以选择(既然说是自动设置的工具,那就说明有手动设置的工具,例如 使用 ip, iw, iwconfig 这些命令设置网络),例如:Connman, netctl, Networ ...
- css实现三角形箭头
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- linux定时任务的设置
1. 键入 crontab -e 编辑crontab服务文件 例如 文件内容如下: */2 * * * * /bin/sh /home/admin/jiaoben/buy/deleteFile.s ...
- include与require的区别?
require()语句的性能与include()相类似,都是包括并运行指定文件.不同之处在于:对include()语句来说,在执行文件时每次都要进行读取和评估:而对于require()来说,文件只处理 ...
- lua 基础 1
--1.1 Chunks--[[Chunk 是一系列语句,Lua 执行的每一块语句,比如一个文件或者交互模式下的每一行都是一个 Chunk.]] -- 1.2 全局变量--[[ 全局变量不需要声明,给 ...
- MSDTC故障排除,DTCTester用法 (二)
摘自:https://support.microsoft.com/zh-cn/kb/293799#bookmark-4 ———————————————————————————— 概要 DTCTeste ...