文档章节

代理模式

o
 osc_5w65ebjo
发布于 07/14 08:24
字数 1181
阅读 31
收藏 0

「深度学习福利」大神带你进阶工程师,立即查看>>>

一 代理模式简介

代理(Proxy)是一种设计模式 提供了对目标对象另外的访问方式

代理对象代理目标对象 达到增强目标对象功能的目的

 

二 静态代理

需要定义接口或者父类 代理对象与目标对象一起实现相同接口或者继承相同父类

优点: 在不修改目标对象的功能前提下 对目标功能扩展

缺点: 因为代理对象需要与目标对象一起实现相同接口或者继承相同父类 所以会有很多代理类 导致类太多 同时 如果接口增加方法 代理对象与目标对象都要维护

1. 接口

/**
 * 接口
 * Created by Hy on 2020/7/10.
 */
public interface IUserService {

    void insertUser();

    String deleteUser(int id);
}

2. 目标对象

/**
 * 目标对象
 * Created by Hy on 2020/7/10.
 */
public class UserService implements IUserService {

    @Override
    public void insertUser() {
        System.out.println("insert ok");
    }

    @Override
    public String deleteUser(int id) {
        System.out.println("delete... ... ...");
        return "id = " + id + " delete ok";
    }
}

3. 代理对象

/**
 * 代理对象
 * Created by Hy on 2020/7/13.
 */
public class UserServiceProxy implements IUserService {

    private IUserService target; //目标对象

    public UserServiceProxy(IUserService target) {
        this.target = target;
    }

    @Override
    public void insertUser() {
        System.out.println("增强方法体 1/2");
        target.insertUser();
        System.out.println("增强方法体 2/2");
    }

    @Override
    public String deleteUser(int id) {
        id++; //增强参数
        String s = target.deleteUser(id);
        s = s + "!!!"; //增强返回值
        return s;
    }
}

4. 测试

@Test
public void test01() {
    // 创建目标对象
    UserService target = new UserService();
    // 创建代理对象
    UserServiceProxy proxy = new UserServiceProxy(target);
    // 使用代理对象调用方法
    proxy.insertUser();
    String s = proxy.deleteUser(1);
    System.out.println(s);
}

 

三 动态代理(接口代理)

需要定义接口让目标对象实现 使用java.lang.reflect.Proxy动态的在内存中构建代理对象

优点: 在不修改目标对象的功能前提下 对目标功能扩展 代理对象不需要实现接口

缺点: 目标对象一定要实现接口 否则不能用动态代理

1. 接口

/**
 * 接口
 * Created by Hy on 2020/7/10.
 */
public interface IUserService {

    void insertUser();

    String deleteUser(int id);
}

2. 目标对象

/**
 * 目标对象
 * Created by Hy on 2020/7/10.
 */
public class UserService implements IUserService {

    @Override
    public void insertUser() {
        System.out.println("insert ok");
    }

    @Override
    public String deleteUser(int id) {
        System.out.println("delete... ... ...");
        return "id = " + id + " delete ok";
    }
}

3. 代理工厂

/**
 * 代理工厂
 * Created by Hy on 2020/7/13.
 */
public class ProxyFactory {

    private Object target; //目标对象

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object createProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            /**
             * 代理对象调用的所有方法都会触发该方法执行
             * @param proxy 代理对象
             * @param method 被代理的方法
             * @param args 被代理的方法传参
             * @return 被代理的方法返回值
             * @throws Throwable 异常
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if ("deleteUser".equals(method.getName())) {
                    // 增强指定方法
                    int id = (int) args[0];
                    id++; //增强参数
                    System.out.println("增强方法体 1/2");
                    String invoke = (String) method.invoke(target, id);
                    invoke = invoke + "!!!"; //增强返回值
                    System.out.println("增强方法体 2/2");
                    return invoke;

                } else {
                    // 其它方法默认实现
                    Object invoke = method.invoke(target, args);
                    return invoke;
                }
            }
        });
    }
}

4. 测试

@Test
public void test01() {
    // 创建目标对象
    UserService target = new UserService();
    System.out.println(target.getClass());
    // 创建代理对象
    IUserService proxy = (IUserService) new ProxyFactory(target).createProxyInstance();
    System.out.println(proxy.getClass());
    // 使用代理对象调用方法
    proxy.insertUser();
    String s = proxy.deleteUser(1);
    System.out.println(s);
}

 

 四 CGLIB代理(子类代理)

通过在内存中构建一个子类对象从而实现对目标对象功能的扩展 CGLIB是一个强大的高性能的代码生成包 底层使用一个小而快的字节码处理框架ASM来转换字节码并生成新的类

优点: 在不修改目标对象的功能前提下 对目标功能扩展 代理对象与目标对象都不需要实现接口

缺点: 需要引入CGLIB的JAR文件

1. 目标对象

/**
 * 目标对象
 * Created by Hy on 2020/7/10.
 */
public class UserService {

    public void insertUser() {
        System.out.println("insert ok");
    }

    public String deleteUser(int id) {
        System.out.println("delete... ... ...");
        return "id = " + id + " delete ok";
    }
}

2. 代理工厂

/**
 * 代理工厂
 * Created by Hy on 2020/7/13.
 */
public class ProxyFactory {

    private Object target; //目标对象

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object createProxyInstance() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            /**
             * 代理对象调用的所有方法都会触发该方法执行
             * @param proxy 代理对象
             * @param method 被代理的方法
             * @param args 被代理的方法传参
             * @param methodProxy 代理的方法
             * @return 被代理的方法返回值
             * @throws Throwable 异常
             */
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                if ("deleteUser".equals(method.getName())) {
                    // 增强指定方法
                    int id = (int) args[0];
                    id++; //增强参数
                    System.out.println("增强方法体 1/2");
                    String invoke = (String) method.invoke(target, id);
                    invoke = invoke + "!!!"; //增强返回值
                    System.out.println("增强方法体 2/2");
                    return invoke;

                } else {
                    // 其它方法默认实现
                    Object invoke = methodProxy.invokeSuper(proxy, args); //等同 method.invoke(target, args);
                    return invoke;
                }
            }
        });
        return enhancer.create();
    }
}

3. 测试

@Test
public void test01() {
    // 创建目标对象
    UserService target = new UserService();
    System.out.println(target.getClass());
    // 创建代理对象
    UserService proxy = (UserService) new ProxyFactory(target).createProxyInstance();
    System.out.println(proxy.getClass());
    // 使用代理对象调用方法
    proxy.insertUser();
    String s = proxy.deleteUser(1);
    System.out.println(s);
}

 

o
粉丝 0
博文 88
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
设计模式Java版,Gitbook开源电子书,含源码

Sunny在CSDN技术博客中陆续发表了100多篇与设计模式学习相关的文章,涵盖了七个面向对象设计原则和24个设计模式(23个GoF设计模式 + 简单工厂模式),为了方便大家学习,http://quanke.name ...

quanke_
2016/05/03
1.9K
5
C++ 事件派发和回调代码库 - eventpp

eventpp 是一个 C++ 事件库,它提供的工具允许应用程序组件通过调度事件并监听它们来相互通信。使用eventpp,您可以非常轻松地实现信号/插槽机制或观察者模式。 特性 支持同步事件调度和异步...

wqking
2018/09/17
797
0
Android设计模式——策略模式之源码使用场景(三)

我的稀土掘金博客同步发布更新:Android设计模式——策略模式之源码使用场景(三) 一、前言 策略模式可以定义一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让...

落地吃鸡
2017/05/01
455
1
iOS 图片浏览器 - YBImageBrowser

YBImageBrowser 是一个 iOS 图片浏览器(支持视频),功能强大,性能优越,轻松集成,易于拓展。 特性 支持 GIF,APNG,WebP 等本地和网络图像类型(由 YYImage、SDWebImage 提供支持)。 支...

匿名
2018/09/24
3.5K
0
React Native 应用基础组件库 - beeshell

介绍 beeshell 是一个 React Native 应用的基础组件库,基于 0.53.3 版本,提供一整套开箱即用的高质量组件,包含 JavaScript(以下简称 JS)组件和复合组件(包含 Native 代码),涉及前端(...

美团技术团队
2018/09/28
2.8K
2

没有更多内容

加载失败,请刷新页面

加载更多

抖音批量发布软件,批量运营200+自媒体账号

抖音批量发布软件,批量运营200+自媒体账号,现在短视频平台大家也可以看的到,流量很大,很多人开通了商品橱窗,在上面进行带货,赚钱也很简单,尤其是抖音这个平台,男女老少都在玩,里面也...

osc_emgrwx5d
10分钟前
0
0
基于MES系统的企业信息化系统的集成

引言 随着网络和科技的发展,互联网技术和电子信息技术已经逐渐融入了我们生活工作的各个环节。在企业中,企业信息化程度的高低也直接影响到企业的运营。企业要想得到快速长远的发展,就要利...

osc_7owgvpdx
11分钟前
17
0
dockerfile源码编译安装nginx、php和harbor

安装docker 环境:基于CentOS Linux release 7.6.1810 注意:以下所有操作基于root用户 #centos7# step 1: 安装必要的一些系统工具yum install -y yum-utils device-mapper-persistent-da...

osc_otuqqtuq
12分钟前
7
0
条形码识别器Dynamsoft Barcode Reader v7.5全新上线!

Dynamsoft Barcode Readerv7.5带来了一些新的参数配置,例如中心定位条形码、二值化模式等。让我们来看看新功能中的一些亮点。 更新 添加了对QR Code Model 1(QR Code规范的旧版本)的支持。...

roffey
13分钟前
6
0
TCP端口的十一种连接状态

TCP端口的十一种连接状态∶ CLOSED∶端口默认是关闭状态。 
LISTEN∶服务器程序开始监听一个端口,就是LISTEN状态。 
 

SYN_RCVD∶三次握手的第二次握手后的端口状态,是收到了客户端发...

程序员面试吧
13分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部