ITKeyword,专注技术干货聚合推荐

注册 | 登录

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

Dream_angel_Z 分享于 2015-05-01

推荐:[设计模式笔记]二. 结构型模式--13.Proxy模式(代理模式)(一)

结构型模式--Proxy模式(代理) 一. 意图 为其他对象提供一种代理以控制对这个对象的访问. 二. 适用性 在需要用比较通用和复杂的对象指针代替简单的指针的时候, 使

2019阿里云全部产品优惠券(新购或升级都可以使用,强烈推荐)
领取地址https://promotion.aliyun.com/ntms/yunparter/invite.html

Proxy 代理模式:解耦

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

实现原理:

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

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

代理模式

代理模式:是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.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

推荐:JAVA设计模式之----------代理模式(Proxy)

这里只是简单的介绍下最基本的代理的使用。 代理,通俗点说 :就是一个人或者一个机构代表另一个人或者另一个机构采取行动。 在一些情况下,一个客户不想或者不

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是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对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中,最重要的一个类是org.apache.struts2.dispatcher.FilterDispatcher用户通过浏览器提交一个HttpServletRequest请求后,请求被在web.xml中的过滤器FilterDispatcher拦截在FilterDispatcher过滤器中首先询问ActionMapper是否需要调用某个Action来处理请求,如果ActionMapper决定需要调用某个请求,FilterDispatcher则把请求的处理交给ActionProxy,ActionProxy通过配置文件struts.xml找到需要调用的Action类,然后ActionProxy创建一个ActionInvocation实例并通用该Action但在调用之前,ActionInvocation会根据配置加载Action相关的Intercepter,等Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的Result结果。

推荐:java设计模式(结构型)之代理模式

第0章:简介 代理模式定义:为其他对象提供一种代理以控制对这个对象的访问 代理模式本质:控制对象访问 参考:http://chjavach.iteye.com/blog/1630401 ,研磨

Proxy 代理模式:解耦 日常开发中的日志、权限、事务处理等。 实现原理: 一个抽象目标类即一个接口,有相关方法名; 一个具体目标类,实现该接口和相关的方法; 一个代理类,调用目标具体类并加

相关阅读排行


用户评论

游客

相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。