博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式(2)代理模式
阅读量:6642 次
发布时间:2019-06-25

本文共 4579 字,大约阅读时间需要 15 分钟。

一.什么是代理模式?

代理就是在不修改被代理对象的前提下,扩展被代理对象的功能

二.代理模式有哪些分类?

静态代理:程序运行前就已经存在代理类的字节码文件,代理类和目标类的关系就已经确定

动态代理:程序在运行时通过反射机制动态创建(jdk代理,cglib代理)

三.静态代理模式的实现

静态代理是通过代理对象与目标对象实现相同的接口,然后在代理对象中调用目标对象中的方法实现的

1.接口

public interface RentHouse {    void rent();}

2.目标对象

public class FindHouse implements RentHouse {    @Override    public void rent() {        System.out.println("我要租房子!");    }}

3.代理对象

public class RentProxy implements RentHouse {    private RentHouse rentHouse;    public RentProxy(RentHouse rentHouse){        this.rentHouse = rentHouse;    }    @Override    public void rent() {        System.out.println("帮你找房子");        rentHouse.rent();        System.out.println("帮你搬家");    }}

4.测试类

public class Test {    public static void main(String[] args) {        FindHouse findHouse = new FindHouse();        RentProxy proxy = new RentProxy(findHouse);        proxy.rent();    }}

四.动态代理之jdk代理

不需要我们手动的创建代理对象,代理对象的生成,是依靠JDK的API(java.lang.reflect.Proxy),动态的在内存中构建代理对象。

1.定义接口

public interface Person {    //上交班费    void giveMoney();}

2.目标对象实现接口

public class Student implements Person {    private String name;    public Student(String name) {        this.name = name;    }    @Override    public void giveMoney() {        try {            //假设数钱花了一秒时间            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(name + "上交班费50元");    }}

3.代理类

public class StuInvocationHandler
implements InvocationHandler { //invocationHandler持有的被代理对象 T target; public StuInvocationHandler(T target) { this.target = target; } //绑定一个委托对象并返回一个代理类 public Object bind(T target) { this.target = target; //取得代理对象 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷) } /** * proxy:代表动态代理对象 * method:代表正在执行的方法 * args:代表调用目标方法时传入的实参 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理执行" +method.getName() + "方法"); //代理过程中插入监测方法,计算该方法耗时 MonitorUtil.start(); Object result = method.invoke(target, args); MonitorUtil.finish(method.getName()); return result; }}

4.代理类中用到的记时工具

public class MonitorUtil {    private static ThreadLocal
tl = new ThreadLocal<>(); public static void start() { tl.set(System.currentTimeMillis()); } //结束时打印耗时 public static void finish(String methodName) { long finishTime = System.currentTimeMillis(); System.out.println(methodName + "方法耗时" + (finishTime - tl.get()) + "ms"); }}

5.执行目标对象时动态的调用代理方法

public class ProxyTest {    public static void main(String[] args) {        //创建一个实例对象,这个对象是被代理的对象        Person zhangsan = new Student("张三");        //创建一个与代理对象相关联的InvocationHandler        InvocationHandler stuHandler = new StuInvocationHandler
(zhangsan); //创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法 Person stuProxy = (Person) ((StuInvocationHandler) stuHandler).bind(zhangsan); //代理执行上交班费的方法 stuProxy.giveMoney(); }}

五.cglib代理

CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:

1.目标对象

public class service {      public String services(){          return "My name is JarremDon";      }  }

2.代理对象

import java.lang.reflect.Method;  import net.sf.cglib.proxy.Enhancer;  import net.sf.cglib.proxy.MethodInterceptor;  import net.sf.cglib.proxy.MethodProxy;  public class CglibProxy implements MethodInterceptor {      //需要代理的原始类      public Object object;      public CglibProxy(Object object){          this.object=object;      }      public Object Proxy(){          //创建加强器          Enhancer enhancer=new Enhancer();          //设置需要加强的类          enhancer.setSuperclass(object.getClass());          //设置回调          enhancer.setCallback(this);          enhancer.setClassLoader(object.getClass().getClassLoader());          return enhancer.create();      }      @Override      public Object intercept(Object arg0, Method arg1, Object[] arg2,              MethodProxy arg3) throws Throwable {          //这里实现加强           Object invoke=arg3.invoke(object, arg2);          return invoke.toString().toUpperCase();      }  }

3.测试类

public class MyTest {      public  static  void main(String args[]){          service s=new service();          CglibProxy proxy=new CglibProxy(s);          service s1=(service) proxy.Proxy();          System.out.println(s1.services());      }  }

转载地址:http://faovo.baihongyu.com/

你可能感兴趣的文章
Microsoft Operations Management Suite 启用NPM网络性能监视
查看>>
新作获京东网双重推荐,成IT媒体新焦点
查看>>
接口测试Fiddler实战
查看>>
网络安全系列之三十一 组策略中的用户权限分配
查看>>
【Python之旅】第四篇(一):Python装饰器
查看>>
Powershell-获取DHCP地址租用信息
查看>>
小白学习大数据测试之hadoop hdfs和MapReduce小实战
查看>>
RMI原理揭秘之远程对象
查看>>
RedHat 7 安装配置Tomcat 8
查看>>
ruby对文件和目录的基本操作
查看>>
在线重启Exadata CELL
查看>>
关于常用到的几个排序,php的实现
查看>>
MongoDB中索引的一点记录
查看>>
LVS学习笔记之LVS简介以及DR原理介绍
查看>>
cpu负载的探讨
查看>>
【go语言】读书随笔
查看>>
python链接mysql常见问题汇总
查看>>
symantec 5220牛刀小试系列(三)
查看>>
监控SQL Server事务复制
查看>>
解决Linux下sqlplus中文乱码问题
查看>>