国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php框架 > 框架设计 > 设计模式(八)代理模式(Proxy)-结构型

设计模式(八)代理模式(Proxy)-结构型

来源:程序员人生   发布时间:2015-05-07 09:40:14 阅读次数:2912次

Proxy 代理模式:解耦

平常开发中的日志权限事务处理等。

实现原理:

  • 1个抽象目标类即1个接口,有相干方法名;
  • 1个具体目标类,实现该接口和相干的方法;
  • 1个代理类,调用目标具体类并加上自己需要的逻辑;
  • 客户端实例化代理类,调用代理类的方法

代理模式实现原理图
代理模式原理图


代理模式

代理模式:是经常使用的java设计模式,他的特点是代理类与拜托类有一样的接口,代理类主要负责为拜托类预处理消息、过滤消息、把消息转发给拜托类,和事后处理消息等。代理类与拜托类之间通常会存在关联关系,1个代理类的对象与1个拜托类的对象关联,代理类的对象本身其实不真正实现服务,而是通过调用拜托类的对象的相干方法,来提供特定的服务。
依照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已存在了。
动态代理:在程序运行时,应用反射机制动态创建而成。

静态代理模式以下:

1.抽象目标类

public interface Subject(){ public void Request(); }

2.具体目标类

public class RealSubject implements Subject(){ public void Request(){ }; }

3.代理类

public class Proxy (){ private RealSubject realSubject; public void Request(){ /**附加逻辑**/ realSubject.Request(); /**附加逻辑**/ }; }

动态代理: JDK动态代理

JDK动态的代理的3个主要类:
Proxy:代理类
InvocationHandler: 接口
Method:要被调用的方法
TaxInterface.java

public interface TaxInterface { public void doTax(); }

Tax.java

public class Tax implements TaxInterface{ @Override public void doTax() { System.out.println("进行所得税计算的逻辑处理"); } }

TimeProxy.java

public class TimeProxy implements InvocationHandler{ private Object obj; //绑定代理对象 public Object bind(Object obj){ this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } //实现代理 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; try { long startTime = System.nanoTime(); result = method.invoke(obj, args); long endTime = System.nanoTime(); System.out.println("计算程序运行时间 :" +(endTime-startTime)); } catch (Exception e) { e.printStackTrace(); } return result; } }

客户端测试:Client.java

public class Client { public static void main(String[] args) { TimeProxy timeProxy = new TimeProxy(); TaxInterface taxInterface = (TaxInterface)timeProxy.bind(new Tax()); taxInterface.doTax(); } }

JDK的动态代理依托接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。

Cglib动态代理

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成1个子类,并覆盖其中方法实现增强,但由于采取的是继承,所以不能对final修饰的类进行代理。
示例以下:
BookFacadeCglib.java

package com.ldw.dao; public interface BookFacade { public void addBook(); }

BookCadeImpl1.java

package com.ldw.dao.impl; /** * 这个是没有实现接口的实现类 * * @author csu.ldw * */ public class BookFacadeImpl1 { public void addBook() { System.out.println("增加图书的普通方法..."); } }

BookFacadeProxy.java

package com.ldw.proxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 使用cglib动态代理 * * @author student * */ public class BookFacadeCglib implements MethodInterceptor { private Object target; /** * 创建代理对象 * * @param target * @return */ public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } @Override // 回调方法 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("事物开始"); proxy.invokeSuper(obj, args); System.out.println("事物结束"); return null; } }

TestCglib.java

package com.ldw.test; import net.battier.dao.impl.BookFacadeImpl1; import net.battier.proxy.BookFacadeCglib; public class TestCglib { public static void main(String[] args) { BookFacadeCglib cglib=new BookFacadeCglib(); BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1()); bookCglib.addBook(); } }

利用

SpringAOP、Struts拦截器、日志管理等。

附加

struts2的拦截器属于AOP思想,采取了代理模式

struts2中,最重要的1个类是org.apache.struts2.dispatcher.FilterDispatcher用户通过阅读器提交1个HttpServletRequest要求后,要求被在web.xml中的过滤器FilterDispatcher拦截在FilterDispatcher过滤器中首先询问ActionMapper是不是需要调用某个Action来处理要求,如果ActionMapper决定需要调用某个要求,FilterDispatcher则把要求的处理交给ActionProxy,ActionProxy通过配置文件struts.xml找到需要调用的Action类,然后ActionProxy创建1个ActionInvocation实例并通用该Action但在调用之前,ActionInvocation会根据配置加载Action相干的Intercepter,等Action履行终了,ActionInvocation负责根据struts.xml中的配置找到对应的Result结果。

生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生