夜话JAVA设计模式之代理模式(Proxy)
代理模式定义:为另一个对象提供一个替身或者占位符以控制对这个对象的访问。---《Head First 设计模式》
代理模式换句话说就是给某一个对象创建一个代理对象,由这个代理对象控制对原对象的引用,并且创建这个代理对象后可以在调用原对象时增加一些额外操作。
下面就由一张代理原理图说明:
1.Subject抽象主题,Proxy和RealSubject都要实现的接口。这允许任何客户都可以像处理RealSubject对象一样地处理Proxy.
2.Proxy:代理类,必须持有所代理对象的引用。
3.RealSubject被代理的类,真正做事的对象。Proxy会控制对RealSubject的访问。
举一个栗子:我们有一个看电影的接口,此时有一个只有看电影的类、还有一个代理商,代理了这部电影,并在看电影开始和结束都加入了广告。
看电影接口:
/**
* @author monkjavaer
* @date 2018/09/05 22:18
*/
public interface Subject { void seeMovie();
}
真正的电影:
/**
* @author monkjavaer
* @date 2018/09/05 22:19
*/
public class RealSubject implements Subject{ @Override
public void seeMovie() {
System.out.println("RealSubject:看电影");
}
}
代理商:
/**
* 代理类
* @author monkjavaer
* @date 2018/09/05 22:20
*/
public class Proxy implements Subject { private Subject subject; public Proxy(Subject subject) {
this.subject = subject;
} @Override
public void seeMovie() {
System.out.println("Proxy:加广告");
subject.seeMovie();
System.out.println("Proxy:加广告");
}
}
测试:
/**
* 测试
* @author monkjavaer
* @date 2018/09/05 22:22
*/
public class ProxyTest {
public static void main(String[] args) { Proxy proxy = new Proxy(new RealSubject());
proxy.seeMovie(); }
}
结果:
Proxy:加广告
RealSubject:看电影
Proxy:加广告
上面就是我们传说中的静态代理。
好了,说了这么多,总结静态代理123。。。
优点: RealSubject通过Proxy实现了功能的增强。 在没有Proxy的时候,RealSubject依然可以执行。
缺点: Proxy要实现和RealSubject同样的接口Subject,Proxy只能为Subject进行代理;如果有很多接口的实现类需要代理,那么就需要很多的代理类。
嗯,,,既然静态代理有这个缺点,那我们啷个办呢。。。。。。
下面我们就引入动态代理。
jdk动态代理:java动态代理位于java.lang.reflect这个包下。其实现原理就是通过反射获取构造函数对象并生成代理类实例。
java Proxy 源码中有这样的一段描述:
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs); /*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
} final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
}
JDK动态代理的实现步骤:
1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
2.创建被代理的类以及接口
3.通过Proxy的静态方法newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理类
4.通过代理类调用方法
下面是具体的java代码实现:
场景:小明吃饭前后都有人帮忙做一些事情。。。
/**
* 人
*/
public interface People { void eat();
}
小明:
public class XiaoMing implements People {
@Override
public void eat() {
System.out.println("小明吃红烧肉");
}
}
代理类:
/**
* 代理类
* @author monkjavaer
* @date 2018/8/31 15:39
*/
public class InvocationHandlerImpl implements InvocationHandler { /**
* 代理的对象
*/
private Object object; public InvocationHandlerImpl(Object object) {
this.object = object;
} /**
*
* @param proxy JDK动态生成的最终代理对象
* @param method 调用真实对象的某个方法的Method对象
* @param args 调用真实对象某个方法时接受的参数
* @return 代理对象
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before:把饭做好"); //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
Object invokeObject = method.invoke(object, args); System.out.println("after:洗碗");
return invokeObject;
}
}
测试:
/**
* 小明吃饭
* @author monkjavaer
* @date 2018/8/31 15:53
*/
public class ProxyTest {
public static void main(String[] args) {
People people = new XiaoMing();
InvocationHandlerImpl handler1 = new InvocationHandlerImpl(people);
//类加载器
ClassLoader classLoader1 = people.getClass().getClassLoader();
//得到全部的接口
Class[] interfaces1 = people.getClass().getInterfaces();
//返回代理类的一个实例
People peopleProxy = (People) Proxy.newProxyInstance(classLoader1, interfaces1, handler1); peopleProxy.eat();
}
}
根据上面的jdk动态代理我们得知:
jdk动态代理有局限,必须针对接口,如果没有接口像上面的例子People、目标没有实现接口那么这个办法就GG了。
这时我们就需要用到另一种代理Cglib动态代理。预知Cglib请听下回分解。。。
夜话JAVA设计模式之代理模式(Proxy)的更多相关文章
- Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景
我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...
- java设计模式6——代理模式
java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...
- 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)
原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...
- Java设计模式:代理模式(转)
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一 ...
- 大熊君说说JS与设计模式之------代理模式Proxy
一,总体概要 1,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...
- 二十四种设计模式:代理模式(Proxy Pattern)
代理模式(Proxy Pattern) 介绍为其他对象提供一个代理以控制对这个对象的访问. 示例有一个Message实体类,某对象对它的操作有Insert()和Get()方法,用一个代理来控制对这个对 ...
- Java基础-设计模式之-代理模式Proxy
代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理 ...
- Java设计模式之代理模式(Proxy)
前言: 最近在研究Retrofit开源框架的时候,其主要核心代码是通过注解标示参数,动态代理模式实现具体接口,反射机制进行参数解析,最终实现发送请求.其实之前在学习Xutils源码的时候,Xutils ...
- java设计模式之八代理模式(Proxy)
其实每个模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你 ...
随机推荐
- ACM_01背包
背包1 Time Limit: 2000/1000ms (Java/Others) Problem Description: 有n个重量和价值分别为Wi,Vi的物品,现从这些物品中挑选出总量不超过 W ...
- 为什么我的对象被 IntelliJ IDEA 悄悄的修改了?
背景 最近,在复习JUC的时候调试了一把ConcurrentLinkedQueue的offer方法,意外的发现Idea在debug模式下竟然会 "自动修改" 已经创建的Ja ...
- Modbus通讯协议简介
Modbus协议简介 Modbus协议最初由Modicon公司开发出来,此协议支持传统的RS-232.RS-422.RS-485和以太网设备,许多工业设备,包括PLC,DCS,智能仪表等都在使用Mod ...
- java 利用Xstream注解生成和解析xml
https://www.oschina.net/code/snippet_116183_14202#23325
- 微信小程序一些常见的坑
1.小程序都报wxss编译错误 解决方法: 在控制台输入openVendor() ,清除里面的wcsc wcsc.exe 然后重启工具 2.微信小程序wx:for警告 Now you can prov ...
- 联想 S5 Pro GT(L78091)免解锁BL 免rec 保数据 ROOT Magisk Xposed 救砖 ZUI5.0.047
>>>重点介绍<<< 第一:本刷机包可卡刷可线刷,刷机包比较大的原因是采用同时兼容卡刷和线刷的格式,所以比较大第二:[卡刷方法]卡刷不要解压刷机包,直接传入手机后用 ...
- vuex的各个细节理解(因人而异)
应用级的状态集中放在store中: 改变状态的方式是提交mutations,这是个同步的事物: 异步逻辑应该封装在action中. const vuex_store = new Vuex.store( ...
- vi 命令学习(二)
[选中文本(可视模式)] v 可视模式 从光标位置开始按正常模式选择文本 V 可视行模式 选中光标经过的完整行 ctrl + v 可视块模式 垂直方向选中文本 [ 撤销和恢复撤销] u undo 撤销 ...
- CAD绘制一个单行文字(com接口VB语言)
主要用到函数说明: _DMxDrawX::DrawText 绘制一个单行文字.详细说明如下: 参数 说明 DOUBLE dPosX >文字的位置的X坐标 DOUBLE dPosY 文字的位置的Y ...
- CAD指定区域绘制一个jpg文件
主要用到函数说明: _DMxDrawX::DrawToJpg 把指定区域的内容绘制一个jpg文件中.详细说明如下: 参数 说明 BSTR sJpgFilePath Jpg文件名 DOUBLE dLbx ...