0

0

Java代理模式详细解析(图文)

黄舟

黄舟

发布时间:2017-03-22 10:19:54

|

1470人浏览过

|

来源于php中文网

原创

这篇文章主要为大家详细介绍了java代理模式的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

代理模式是我们比较常用的设计模式之一。其中新思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信,代理模式一般涉及到的角色有:

抽象角色:声明真实对象和代理对象的共同接口;

代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

立即学习Java免费学习笔记(深入)”;

以下以发送消息为例来说明一个简单的代理模式的基本实现:

首先明确目的:有一条消息,需要把这个消息发送出去,根据这个目的定义对应接口MessageHandler。需要的附加操作:假设需要验证消息的长度不能超过指定长度并且不能为空,并且我们需要统计相关信息发送到次数,超过指定的次数我们需要输出警报。我们通过代理模式来实现这个附加的操作。下面为对应的类关系图及示例代码。 


//接口定义  
public interface MessageHandler {  
public void sendMessage(String msg);  
}  
//通过Email方式发送消息的实现类  
public class EmailMessage implements MessageHandler {  
@Override  
public void sendMessage(String msg) {  
// TODO Auto-generated method stub  
System.out.println(msg+" send!!");  
}  
}  
//消息处理的代理类  
public class MessageProxy implements MessageHandler {  
private static int count;  
private MessageHandler emailMsg;  
@Override  
public void sendMessage(String msg) {  
// TODO Auto-generated method stub  
if(checkMessage(msg))  
{  
if(emailMsg==null) emailMsg=new EmailMessage();  
count++;  
emailMsg.sendMessage(msg);  
System.out.println("Message sent:"+count);  
}  
}  
private boolean checkMessage(String msg) {  
return msg != null && msg.length() > 10;  
}  
}  
//调用类  
public class MainClass {  
private static void runProxy(MessageHandler handler)  
{  
handler.sendMessage("message for test");  
}  
/** 
 * @param args 
 */  
public static void main(String[] args) {  
// TODO Auto-generated method stub  
runProxy(new EmailMessage());  
System.out.println("++++++++++++++++Pjroxy++++++++++++++++++");  
runProxy(new MessageProxy());  
}  
}  
//输出  
message for test send!!  
++++++++++++++++Pjroxy++++++++++++++++++  
message for test send!!  
Message sent:1

 在例子中我们可以方便的在消息发送过程中添加各种需要的附加处理方式,也能方便的替换消息的处理方式,如将通过Email发送消息替换为通过短信发送消息,而调用方不会有丝毫察觉!在任何你想要将一些额外操作分离到具体对象之外,特别是希望能够很容易做出修改,或者想在具体对象的方法执行前插入一些额外操作的时候,代理就显得十分有用!

动态代理

凡人网络购物系统jsp版(JspShop)
凡人网络购物系统jsp版(JspShop)

基于jsp+javabean+access(mysql)三层结构的动态购物网站,v1.2包含v1.0中未公开的数据库连接 的java源文件 一,网站前台功能: 产品二级分类展示:一级分类--二级分类--产品列表--详细介绍(名称,图片,市场价,会员价,是否推荐,功能介绍等) 产品搜索:关键字模糊搜索 定购产品:选择商品--确认定购--填写收货人信息--选择付款方式--订单号自动生成(限登录用户)

下载

Java中动态代理机制的引入使得代理模式的思想更加完善与进步,它允许动态的创建代理并支持对动态的对所代理的方法进行调用。Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。

(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:
Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。 下面我们通过动态代理来重新实现上面发送信息的例子!

 

在上面的例子基础上,我们先添加一个通过短信来发送消息的处理类:


public class SmsMessage implements MessageHandler {  
@Override  
public void sendMessage(String msg) {  
// TODO Auto-generated method stub  
System.out.println("SMS Message :" + msg+" sent !");  
}  
}  
//动态代理类  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
public class DynamicMessageProxy implements InvocationHandler {  
private static int count;  
private MessageHandler msgHandler;  
public DynamicMessageProxy(MessageHandler handler) {  
msgHandler = handler;  
}  
@Override  
public Object invoke(Object proxy, Method method, Object[] args)  
throws Throwable {  
// TODO Auto-generated method stub  
System.out.println("++++++++=============+++++++++");  
System.out.println("proxy:" + proxy.getClass());  
System.out.println("method:" + method);  
System.out.println("++++++++=============+++++++++");  
if (args != null && args.length == 1 && checkMessage((String) args[0])) {  
count++;  
System.out.println("Message sent:" + count);  
return method.invoke(msgHandler, args);  
}  
return null;  
}  
private boolean checkMessage(String msg) {  
return msg != null && msg.length() > 10;  
}  
}  
//下面是调用  
import java.lang.reflect.Proxy;  
public class MainClass {  
private static void runProxy(MessageHandler handler) {  
handler.sendMessage("message for test");  
}  
/** 
 * @param args 
 */  
public static void main(String[] args) {  
// TODO Auto-generated method stub  
// runProxy(new EmailMessage());  
// System.out.println("++++++++++++++++Proxy++++++++++++++++++");  
// runProxy(new MessageProxy());  
MessageHandler handler = new EmailMessage();  
runProxy(handler);  
MessageHandler proxy = (MessageHandler) Proxy.newProxyInstance(  
MessageHandler.class.getClassLoader(),  
new Class[] { MessageHandler.class }, new DynamicMessageProxy(  
handler));  
runProxy(proxy);  
System.out.println("++++++++++++++++++++++++++++++++++");  
// 短信方式  
handler = new SmsMessage();  
runProxy(handler);  
proxy = (MessageHandler) Proxy.newProxyInstance(MessageHandler.class  
.getClassLoader(), new Class[] { MessageHandler.class },  
new DynamicMessageProxy(handler));  
runProxy(proxy);  
}  
}  
//下面为以上方法的输出:  
message for test send!!  
++++++++=============+++++++++  
proxy:class $Proxy0  
method:public abstract void MessageHandler.sendMessage(java.lang.String)  
++++++++=============+++++++++  
Message sent:1  
message for test send!!  
++++++++++++++++++++++++++++++++++  
SMS Message :message for test sent !  
++++++++=============+++++++++  
proxy:class $Proxy0  
method:public abstract void MessageHandler.sendMessage(java.lang.String)  
++++++++=============+++++++++  
Message sent:2  
SMS Message :message for test sent !

 以上例子中,通过调用Proxy.newProxyInstance方法创建动态代理对象,该方法需要传入一个 类加载器、一组希望代理实现的接口列表、InvocationHandler 接口的一个具体实现。动态代理可以将所有调用重定向到调用处理器,通常我们会向该处理器传递一个时间对象的引用。invoke()方法中传递进来了代理对象,当你需要区分请求来源时这是非常有用的,例如你可以通过判断传入的方法名屏蔽掉某些方法的执行!动态代理机制并不是会很频繁使用的方法,它通常用来解决一些特定情况下的问题,因此不要盲目的为了使用而使用,要根据自己的实际需求来决定!

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
全国统一发票查询平台入口合集
全国统一发票查询平台入口合集

本专题整合了全国统一发票查询入口地址合集,阅读专题下面的文章了解更多详细入口。

19

2026.02.03

短剧入口地址汇总
短剧入口地址汇总

本专题整合了短剧app推荐平台,阅读专题下面的文章了解更多详细入口。

27

2026.02.03

植物大战僵尸版本入口地址汇总
植物大战僵尸版本入口地址汇总

本专题整合了植物大战僵尸版本入口地址汇总,前往文章中寻找想要的答案。

15

2026.02.03

c语言中/相关合集
c语言中/相关合集

本专题整合了c语言中/的用法、含义解释。阅读专题下面的文章了解更多详细内容。

3

2026.02.03

漫蛙漫画网页版入口与正版在线阅读 漫蛙MANWA官网访问专题
漫蛙漫画网页版入口与正版在线阅读 漫蛙MANWA官网访问专题

本专题围绕漫蛙漫画(Manwa / Manwa2)官网网页版入口进行整理,涵盖漫蛙漫画官方主页访问方式、网页版在线阅读入口、台版正版漫画浏览说明及基础使用指引,帮助用户快速进入漫蛙漫画官网,稳定在线阅读正版漫画内容,避免误入非官方页面。

13

2026.02.03

Yandex官网入口与俄罗斯搜索引擎访问指南 Yandex中文登录与网页版入口
Yandex官网入口与俄罗斯搜索引擎访问指南 Yandex中文登录与网页版入口

本专题汇总了俄罗斯知名搜索引擎 Yandex 的官网入口、免登录访问地址、中文登录方法与网页版使用指南,帮助用户稳定访问 Yandex 官网,并提供一站式入口汇总。无论是登录入口还是在线搜索,用户都能快速获取最新稳定的访问链接与使用指南。

114

2026.02.03

Java 设计模式与重构实践
Java 设计模式与重构实践

本专题专注讲解 Java 中常用的设计模式,包括单例模式、工厂模式、观察者模式、策略模式等,并结合代码重构实践,帮助学习者掌握 如何运用设计模式优化代码结构,提高代码的可读性、可维护性和扩展性。通过具体示例,展示设计模式如何解决实际开发中的复杂问题。

3

2026.02.03

C# 并发与异步编程
C# 并发与异步编程

本专题系统讲解 C# 异步编程与并发控制,重点介绍 async 和 await 关键字、Task 类、线程池管理、并发数据结构、死锁与线程安全问题。通过多个实战项目,帮助学习者掌握 如何在 C# 中编写高效的异步代码,提升应用的并发性能与响应速度。

2

2026.02.03

Python 强化学习与深度Q网络(DQN)
Python 强化学习与深度Q网络(DQN)

本专题深入讲解 Python 在强化学习(Reinforcement Learning)中的应用,重点介绍 深度Q网络(DQN) 及其实现方法,涵盖 Q-learning 算法、深度学习与神经网络的结合、环境模拟与奖励机制设计、探索与利用的平衡等。通过构建一个简单的游戏AI,帮助学习者掌握 如何使用 Python 训练智能体在动态环境中作出决策。

3

2026.02.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.2万人学习

C# 教程
C# 教程

共94课时 | 8.4万人学习

Java 教程
Java 教程

共578课时 | 56.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号