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

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

不知不觉今天已经7月底了,时间过得真快,这个月真热,这篇文章主要来介绍代理模式。

概述

代理模式为另一个对象提供一个替身或者占位符以控制对这个对象的访问

如下图所示

img_883d52675407cf9762531b63bb124848.png

UML类图

img_c5e2d856653bfe58c24bbb0355a94696.png

代理模式类别

img_f3b76f994df79810357753ad791ede77.png

代码实现

这里是结合springAop,仿造它的实现

静态代理

public interface Subject {    void request();}// 请求的真实目标对象public class RealSubject implements Subject {    @Override    public void request() {        System.out.println("real subject execute request");    }}// 代理对象public class Proxy implements Subject {    private RealSubject realSubject;    public Proxy(RealSubject realSubject) {        this.realSubject = realSubject;    }    @Override    public void request() {        System.out.println("before");        try {            realSubject.request();        } catch (Exception e) {            System.out.println("ex:" + e);            throw e;        } finally {            System.out.println("after");        }    }}

客户端调用代码

public class Client {    public static void main(String[] args) throws Exception {        Subject subject = new Proxy(new RealSubject());        subject.request();    }}

运行结果

beforereal subject execute requestafter

静态代理有一个很明显的缺点:代理的方法越多,重复代码越多。

就不符合DRY原则。于是 就产生了动态代理

动态代理

jdk代理

JDK 为我们提供了一种动态代理的实现,通过实现 InvocationHandler 接口来实现动态代理。

代理类代码

public class JdkProxySubject implements InvocationHandler {    private RealSubject realSubject;    public JdkProxySubject(RealSubject realSubject) {        this.realSubject = realSubject;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("before");        Object result = null;        try {            result = method.invoke(realSubject, args);        } catch (Exception e) {            System.out.println("ex" + e);            throw e;        } finally {            System.out.println("after");        }        return result;    }}

客户端类代码

public class Client {    public static void main(String[] args) throws Exception {        Subject subject = (Subject) Proxy.newProxyInstance(Client.class                .getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));        subject.request();    }}

运行结果

beforereal subject execute requestafter

上面讲了动态代理是解决代码重复的问题。我们来验证下

首先,在Subject 接口中增加一个hello方法

public interface Subject {    void request();    void hello();}public class RealSubject implements Subject {    @Override    public void request() {        System.out.println("real subject execute request");    }    @Override    public void hello() {        System.out.println("real subject execute hello");    }}

静态代理类 如果想要代理hello 这个方法。就要在代理类中实现这个方法

public class Proxy implements Subject {    private RealSubject realSubject;    public Proxy(RealSubject realSubject) {        this.realSubject = realSubject;    }    @Override    public void hello() {        ...    }}

我们看动态代理类,无需改变,直接运行测试类

public class Client {    public static void main(String[] args) throws Exception {        Subject subject = (Subject) Proxy.newProxyInstance(Client.class                .getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));        subject.hello();    }}

运行结果

beforereal subject execute helloafter
Cglib代理

代理类

public class DemoMethodInterceptor implements MethodInterceptor {    @Override    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("before in cglib");        Object result = null;        try {            result = proxy.invokeSuper(object,args);        }catch (Exception e){            System.out.println("get ex :" + e.getMessage());            throw e;        }finally {            System.out.println("after in cglib");        }        return result;    }}

调用

public class Client {    public static void main(String[] args) {        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(RealSubject.class);        enhancer.setCallback(new DemoMethodInterceptor());        Subject subject = (Subject) enhancer.create();        subject.request();    }}

运行结果

before in cglibreal subject execute requestafter in cglib

JDK代理和Cglib代理区别

  • JDK代理只能针对有接口的类的方法进行代理
  • Cglib基于继承来实现代理,无法对static、final 类进行代理
  • Cglib基于继承来实现代理,无法对private、static 方法 进行代理

代理模式暂时先分析到这,玩的开心!

学习不是要么0分,要么100分的。80分是收获;60分是收获;20分也是收获。有收获最重要。但是因为着眼于自己的不完美,最终放弃了,那就是彻底的0分了。

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

你可能感兴趣的文章
React Native(Android)调用支付宝
查看>>
关于redis的几件小事(六)redis的持久化
查看>>
GO_GIN_不同文件下html模版渲染
查看>>
package.json
查看>>
webpack4+babel7+eslint+editorconfig+react-hot-loader 搭建react开发环境
查看>>
Maven 插件
查看>>
深入理解 Java 虚拟机
查看>>
初探Angular6.x---进入用户编辑模块
查看>>
计算机基础知识复习
查看>>
【前端词典】实现 Canvas 下雪背景引发的性能思考
查看>>
大佬是怎么思考设计MySQL优化方案的?
查看>>
<三体> 给岁月以文明, 给时光以生命
查看>>
Android开发 - 掌握ConstraintLayout(九)分组(Group)
查看>>
springboot+logback日志异步数据库
查看>>
Typescript教程之函数
查看>>
Android 高效安全加载图片
查看>>
vue中数组变动不被监测问题
查看>>
3.31
查看>>
类对象定义 二
查看>>
收费视频网站Netflix:用户到底想要“点”什么?
查看>>