Java常见设计模式之代理模式
指由一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其它相关业务的处理。比如生活中的通过代理访问网络,客户通过网络代理连接网络(具体业务),由代理服务器完成用户权限和访问限制等与上网相关的其他操作(相关业务)。代理的思想在我们日常生活中无处不在。下面我通过一个简单的代码先大致了解一下代理的相关内。
示例代码如下:
package com.yonyou.test; /**
* 创建一个上网的接口
* @author 小浩
* @创建日期 2015-4-6
*/
public interface Network {
//用户真正的上网需求
void browse();
}
package com.yonyou.test; /**
* 真正的上网需求类,实现Network接口
* @author 小浩
* @创建日期 2015-4-6
*/
public class Real implements Network{ @Override
public void browse() {
System.out.println("您好,当前用户正在上网操作~~~");
} }
package com.yonyou.test; /**
* 创建一个代理接口
* @author 小浩
* @创建日期 2015-4-6
*/
public class Proxy implements Network{
Network network=null;
//初始化被代理对象
public Proxy(Network network){
this.network=network;
}
//模式权限检查的操作
public void check(){
// 模拟权限检查
System.out.println("您好,我们正在检查当前用户是否有上网的权限...");
} @Override
public void browse() {
//增强操作,模拟权限检查
check();
//用户真正的操作
network.browse();
} }
package com.yonyou.test; /**
* TreeSet测试类
* @author 小浩
* @创建日期 2015-4-3
*/
public class Test{
public static void main(String[] args) {
//创建代理类
Network network=new Proxy(new Real());
network.browse();
}
}
一般在哪些地方需要使用代理:
1 创建目标对象的开销比较大,而且在当前程序中,还有可能使用不到目标对象的全部方法
2 需要对目标对象进行增强处理
下面对常见的代理方式进行讲解。
1、静态代理(static proxy)
因为静态代理比较简单,下面我们就直接上例子:
package com.xiaohao.proxystatic; /** 定义电脑的通用接口 */
public interface Computer {
//定义电脑开机的接口
public void power();
}
package com.xiaohao.proxystatic; public class ComputerProxy implements Computer{ private Computer computer; public ComputerProxy(Computer computer){
this.computer=computer;
} @Override
public void power() {
//增强处理的方法,before
System.out.println("您好,系统正在加载中,请稍后.............");
//调用相应的原来的方法
computer.power();
//增强处理的方法,after
System.out.println("恭喜您,您已经成功开机,Congratulation~~~~~~~"); } }
package com.xiaohao.proxystatic; public class Hp implements Computer{ @Override
public void power() {
System.out.println("您好,欢迎使用惠普电脑~~~~~"); } }
package com.xiaohao.proxystatic; public class Lenovo implements Computer{ @Override
public void power() {
System.out.println("您好,欢迎您使用联想电脑~~~~~~~~"); } }
package com.xiaohao.proxystatic; public class Test { public static void main(String[] args) {
//创建惠普电脑对象
Hp hp=new Hp(); //创建联想电脑对象
Lenovo lenovo=new Lenovo(); //创建电脑的代理类,使相应的电脑的方法得到相应的加强
ComputerProxy computerProxyHp=new ComputerProxy(hp);
ComputerProxy computerProxyLenovo=new ComputerProxy(lenovo); computerProxyHp.power(); System.out.println("-------------------------------------------------------------------"); computerProxyLenovo.power(); System.out.println("-------------------------------------------------------------------");
} }
2、动态代理(dynamic proxy)
观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。常见的动态代理有两种方式,一种为jdk动态代理,一种为cglib动态代理。下面我们分别来介绍一下它们。
JDK动态代理:
package com.xiaohao.proxydynamic; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class ComputerProxy implements InvocationHandler{ //创建被代理的对象
private Object computer; //绑定需要代理的对象
public Object bind(Computer computer){
this.computer=computer;
return Proxy.newProxyInstance(computer.getClass().getClassLoader(),
computer.getClass().getInterfaces()
,this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//增强处理的方法,before
System.out.println("您好,系统正在加载中,请稍后.............");
//调用相应的原来的方法
Object result=method.invoke(computer,args);
//增强处理的方法,after
System.out.println("恭喜您,您已经成功开机,Congratulation~~~~~~~"); return result;
}
}
package com.xiaohao.proxydynamic; public class Test { public static void main(String[] args) {
//创建惠普电脑对象
Hp hp=new Hp(); //创建联想电脑对象
Lenovo lenovo=new Lenovo(); //创建电脑的代理类,使相应的电脑的方法得到相应的加强
ComputerProxy computerProxy=new ComputerProxy(); Computer computer=(Computer) computerProxy.bind(hp); computer.power(); System.out.println("-------------------------------------------------------------------"); computer=(Computer) computerProxy.bind(lenovo); computer.power(); System.out.println("-------------------------------------------------------------------");
} }
对于jdk动态代理而言,我们需要被代理的目标类实现相应的接口。对于jdk动态代理的原理的讲解可以参考:
http://www.cnblogs.com/xiohao/p/4397359.html
cglib动态代理:
针对于jdk动态代理需要在被代理类实现相应的接口,但是针对于某些没有实现指定接口的类,就显得无能为力了。
这时我们可以使用第三方插件cglib,来实现对目标对象的增强处理。(在使用的过程中需要导入cglib的相关包)。
具体的使用格式请看下面的内容吧。
package com.xiaohao.proxycglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; //import org.aopalliance.intercept.MethodInterceptor;
//import org.aopalliance.intercept.MethodInvocation; public class ComputerProxy implements MethodInterceptor{ //创建被代理对象
private Object computer; public Object bind(Object computer){
this.computer=computer;
Enhancer enhancer=new Enhancer();
//设置要代理的类,使代理类作为被代理类的父类
enhancer.setSuperclass(this.computer.getClass());
//回调相应的方法
enhancer.setCallback(this);
//创建相应的代理对象,并返回相应的代理对象
return enhancer.create(); } // 回调方法
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
System.out.println("您好,系统正在加载中,请稍后.............");
arg3.invokeSuper(arg0,arg2);
System.out.println("恭喜您,您已经成功开机,Congratulation~~~~~~~");
return null;
} }
package com.xiaohao.proxycglib; public class Test { public static void main(String[] args) { //创建被代理对象
Hp hp=new Hp();
//创建被代理对象
Lenovo lenovo=new Lenovo(); ComputerProxy computerProxy=new ComputerProxy(); //绑定相应的目标代理类
hp=(Hp) computerProxy.bind(hp);
lenovo=(Lenovo) computerProxy.bind(lenovo); hp.power(); System.out.println("-------------------------------------------------------------------"); lenovo.power(); System.out.println("-------------------------------------------------------------------");
} }
下面是Spring整合cglib后的一种使用方式,原理差不多,感兴趣的可以简单的看一下:
package com.xiaohao.proxycgli; import java.lang.reflect.Method; import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; //import org.aopalliance.intercept.MethodInterceptor;
//import org.aopalliance.intercept.MethodInvocation; public class ComputerProxy implements MethodInterceptor{ @Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
//增强处理的方法,before
System.out.println("您好,系统正在加载中,请稍后.............");
//调用相应的原来的方法
Object result=arg3.invokeSuper(arg0, arg2);
//增强处理的方法,after
System.out.println("恭喜您,您已经成功开机,Congratulation~~~~~~~");
return result;
} // @Override
// public Object invoke(MethodInvocation arg0) throws Throwable {
// //增强处理的方法,before
// System.out.println("您好,系统正在加载中,请稍后.............");
// //调用相应的原来的方法
// Object result=arg0.proceed();
// //增强处理的方法,after
// System.out.println("恭喜您,您已经成功开机,Congratulation~~~~~~~");
// return result;
// } }
Java常见设计模式之代理模式的更多相关文章
- Java基础-设计模式之-代理模式Proxy
代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理 ...
- Java常见设计模式之工厂模式
工厂模式在我们日常的应用中应当算是比较广泛的一种设计模式了.今天让我们一起来学习一下,工厂的设计模式. 工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple F ...
- 基于JAVA的设计模式之代理模式
概念 王宝强有一个经纪人叫宋喆,这个经纪人很吊,可以代理王宝强做一系列的事情,与粉丝活动.王宝强的微博维护.安排王宝强的行程以及什么什么等等.如果王宝强一个人做岂不是累死.通过这个代理人为王宝强节省了 ...
- Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景
我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...
- 夜话JAVA设计模式之代理模式(Proxy)
代理模式定义:为另一个对象提供一个替身或者占位符以控制对这个对象的访问.---<Head First 设计模式> 代理模式换句话说就是给某一个对象创建一个代理对象,由这个代理对象控制对原对 ...
- Java设计模式:代理模式(转)
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一 ...
- java设计模式6——代理模式
java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...
- C#设计模式(13)——代理模式(Proxy Pattern)
一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让代 ...
- Java 反射 设计模式 动态代理机制详解 [ 转载 ]
Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...
随机推荐
- 016-Spring Boot JDBC
一.数据源装配 通过查看代码可知,默认已装配了数据源和JdbcTemplate System.out.println(context.getBean(DataSource.class)); Syste ...
- Basis 基础
[转自 http://www.cnblogs.com/elegantok/archive/2008/11/03/1325163.html] 1 Basis1. Unix操作 更改口令 passwd e ...
- Java 线程的终止-interrupt
Java线程的终止——interrupt 取消/关闭的场景 我们知道,通过线程的start方法启动一个线程后,线程开始执行run方法,run方法运行结束后线程退出,那为什么还需要结束一个线程呢?有多种 ...
- python3 生成随即激活码
import string import random #激活码中的字符和数字 field = string.ascii_letters + string.digits #获得四个字母和数字的随即组合 ...
- Linux中cp命令不提示直接覆盖的方法
新做了服务器,cp覆盖时,无论加什么参数-f之类的还是提示是否覆盖,这在大量cp覆盖操作的时候是不能忍受的. 把a目录下的文件复制到b目录 cp –r a/* b 执行上面的命令时,b存在的每个文件都 ...
- iOS 图文混排 链接 可点击
对于这个话题 我想到 1 第一个解决方法就是使用 webView 比较经典 把所有复杂工作都交给控件本身去处理了, 但是好像好多需要自定义的地方 没法从 webView获得响应回调 :(估计也可以实 ...
- Hadoop如何修改HDFS文件存储块大小
一. 临时修改可以在执行上传文件命令时,显示地指定存储的块大小.1. 查看当前 HDFS文件块大小我这里查看HDFS上的TEST目录下的jdk-7u25-linux-x64.gz 文件存储块大小.1 ...
- 解决COMODO Internet Security更新慢或失败的问题
方法一: COMODO 默认更新服务器只有一个:http://download.comodo.com/ 我电信网络更新速度非常慢: 实在没有办法了,找到了几个更新服务器: http://eu1.dow ...
- 总结最近写的h5项目
其实最近最大的感触就是真正独立完结一个项目的人学到的东西是最多,但并不意味着自己已全部吸收,还是得消化消化 最近做了一个移动端的h5页面,感兴趣的可以访问看一看:http://app.500jia.c ...
- SpringCloud-服务的注册与发现(Eureka)
SpringCloud 简介 SpringCloud为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选.分布式会话等等.它运行环境简 ...