全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

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发送消息替换为通过短信发送消息,而调用方不会有丝毫察觉!在任何你想要将一些额外操作分离到具体对象之外,特别是希望能够很容易做出修改,或者想在具体对象的方法执行前插入一些额外操作的时候,代理就显得十分有用!

动态代理

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代理模式实例分析  # 23种设计模式(7) java代理模式  # 轻松掌握Java代理模式  # java代理模式与动态代理模式详解  # Java基础之让你彻底搞懂代理模式  # Java通俗易懂系列设计模式之代理模式  # Java线程创建静态代理模式代码实例  # Java简单实现动态代理模式过程解析  # 浅谈JAVA设计模式之代理模式  # Java设计模式之代理模式详解  # 发送消息  # 涉及到  # 你必须  # 自己的  # 这是  # 是在  # 来了  # 会有  # 你可以  # 第一个  # 是这样  # 基础上  # 都能  # 是指  # 也能  # 当你  # 其他的  # 而在  # 你想  # 很容易 


相关文章: 建站之星后台密码遗忘?如何快速找回?  如何制作算命网站,怎么注册算命网站?  建站之星价格显示格式升级,你的预算足够吗?  小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?  如何规划企业建站流程的关键步骤?  建站之星如何实现网站加密操作?  内网网站制作软件,内网的网站如何发布到外网?  制作网站的过程怎么写,用凡科建站如何制作自己的网站?  山东网站制作公司有哪些,山东大源集团官网?  网站制作价目表怎么做,珍爱网婚介费用多少?  免费公司网站制作软件,如何申请免费主页空间做自己的网站?  如何通过虚拟机搭建网站?详细步骤解析  制作网站怎么制作,*游戏网站怎么搭建?  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  如何确保西部建站助手FTP传输的安全性?  用v-html解决Vue.js渲染中html标签不被解析的问题  济南网站制作的价格,历城一职专官方网站?  如何通过可视化优化提升建站效果?  相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?  公司网站设计制作厂家,怎么创建自己的一个网站?  湖北网站制作公司有哪些,湖北清能集团官网?  如何通过PHP快速构建高效问答网站功能?  专业网站制作企业网站,如何制作一个企业网站,建设网站的基本步骤有哪些?  如何在云主机快速搭建网站站点?  广州营销型建站服务商推荐:技术优势与SEO优化解析  独立制作一个网站多少钱,建立网站需要花多少钱?  如何在阿里云高效完成企业建站全流程?  青岛网站建设如何选择本地服务器?  如何基于云服务器快速搭建个人网站?  定制建站价位费用解析与套餐推荐全攻略  如何生成腾讯云建站专用兑换码?  如何在云虚拟主机上快速搭建个人网站?  Python文件管理规范_工程实践说明【指导】  建站之星后台密码如何安全设置与找回?  网站制作大概要多少钱一个,做一个平台网站大概多少钱?  制作网站的软件免费下载,免费制作app哪个平台好?  如何零基础开发自助建站系统?完整教程解析  简易网站制作视频教程,使用记事本编写一个简单的网页html文件?  PHP 500报错的快速解决方法  如何配置FTP站点权限与安全设置?  建站主机服务器选购指南:轻量应用与VPS配置解析  如何用免费手机建站系统零基础打造专业网站?  如何在IIS中新建站点并解决端口绑定冲突?  宝塔新建站点报错如何解决?  如何在Ubuntu系统下快速搭建WordPress个人网站?  公司网站制作费用多少,为公司建立一个网站需要哪些费用?  网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?  网站制作员失业,怎样查看自己网站的注册者?  佛山网站制作系统,佛山企业变更地址网上办理步骤?  深圳企业网站制作设计,在深圳如何网上全流程注册公司? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。