Chiriri's blog Chiriri's blog
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)

Iekr

苦逼后端开发
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)
  • JavaSE

  • JavaEE

  • Linux

  • MySQL

  • NoSQL

  • Python

  • Python模块

  • 机器学习

  • 设计模式

    • 设计模式的概念
    • 创建型模式
    • 单例(Singleton)模式
    • 原型(Prototype)模式
    • 工厂(Factory)模式
    • 建造者(Builder)模式
    • 结构型模式(Structural Pattern)
    • 适配器模式(Adapter Pattern)
    • 桥接模式(Bridge Pattern)
    • 装饰器模式(Decorator、Wrapper(包装) Pattern)
    • 代理模式(Proxy Pattern)
      • 静态代理
      • JDK动态代理
      • cglib动态代理
      • 应用场景
      • 区别-装饰器、代理
    • 外观模式(Facade Pattern)
    • 组合模式(Composite Pattern)
    • 享元模式(Flyweight Pattern)
    • 行为型模式(Behavioral Patterns)
    • 模板方法(Template Method)
    • 策略(Strategy)模式
    • 状态(State)模式
    • 中介者(Mediator)模式
    • 观察者(Observer)模式
    • 备忘录(Memento)模式
    • 解释器(Interpreter)模式
    • 命令(Command)模式
    • 迭代器(Iterator)模式
    • 访问者(Visitor)模式
    • 职责链(Chain of Responsibility)模式
    • 总结
  • 传智健康

  • 畅购商城

  • 博客项目

  • JVM

  • JUC

  • Golang

  • Kubernetes

  • 硅谷课堂

  • C

  • 源码

  • 神领物流

  • RocketMQ

  • 短链平台

  • 后端
  • 设计模式
Iekr
2022-04-22
目录

代理模式(Proxy Pattern)

# 代理模式(Proxy Pattern)

代理模式 (Proxy Pattern) , 给某一个对象提供一个代理,并由代理对象控制对原对象的引用,对象结构型模式。这种也是静态代理

image-20220422173823045

代理模式包含如下角色:

Subject: 抽象主体角色 (抽象类或接口)

Proxy: 代理主体角色 (代理对象类)

RealSubject: 真实主体角色 (被代理对象类)

# 静态代理

代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象。这样做的好处 是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。

  • 静态代理就是装饰器模式
  • 装饰器模式是代理模式的一种

Subject: 抽象主体角色 (抽象类或接口)

/**
 * 抽象主体 被代理角色
 */
public interface ManTikTok {
    void tiktok();
}
1
2
3
4
5
6

Proxy: 代理主体角色 (代理对象类)

/**
 * 代理一般和被代理对象属于同一个接口
 * 静态代理就是装饰器模式
 * 装饰器模式是代理模式的一种
 */
public class TiktokProxy implements ManTikTok{

    //被代理对象
    private MiTikTok miTikTok;

    public TiktokProxy(MiTikTok miTikTok) {
        this.miTikTok = miTikTok;
    }

    @Override
    public void tiktok() {
        System.out.println("增强功能");
        miTikTok.tiktok();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

RealSubject: 真实主体角色 (被代理对象类)

/**
 * subject 主体
 *
 */
public class MiTikTok  implements ManTikTok{
    @Override
    public void tiktok() {
        System.out.println("雷军正在直播");
    }
}
1
2
3
4
5
6
7
8
9
10

测试

public static void main(String[] args) {
    TiktokProxy tiktokProxy = new TiktokProxy(new MiTikTok());
    tiktokProxy.tiktok();
}
1
2
3
4

# JDK 动态代理

利用 JDK 动态代理 反射增强

Subject: 抽象主体角色 (抽象类或接口)

/**
 * 抽象主体 被代理角色
 */
public interface ManTikTok {
    void tiktok();
}
1
2
3
4
5
6
public interface SellTiktok {
    void send();
}
1
2
3

Proxy: 代理主体角色 (代理对象类)

public class JdkTiktokProxy<T> implements InvocationHandler {
    private T target;


    //接受被代理对象
    public JdkTiktokProxy(T target) {
        this.target = target;
    }

    /**
     * 获取被代理对象的 代理对象
     *
     * @param t
     * @param <T>
     * @return
     */
    public static <T> T getProxy(T t) {


        /**
         * ClassLoader loader,  当前被代理的类加载器
         * Class<?>[] interfaces, 当前被代理对象所实现的所有接口  必须要有接口 如果无则会报异常 代理对象无法创建
         * InvocationHandler h 当前被代理对象执行目标方法的时候我们使用h可以定义拦截增强方法
         */
        Object o = Proxy.newProxyInstance(t.getClass().getClassLoader(),
                t.getClass().getInterfaces(),
                new JdkTiktokProxy<>(t)
        );
        return (T) o;
    }

    /**
     * 定义目标方法的拦截逻辑:每个方法都会进来的
     *
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //反射执行
        System.out.println("被代理对象原身方法被执行");
        Object invoke = method.invoke(target, args);
        System.out.println("返回值" + invoke);
        return invoke;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

RealSubject: 真实主体角色 (被代理对象类)

/**
 * subject 主体
 *
 */
public class MiTikTok  implements ManTikTok,SellTiktok {
    @Override
    public void tiktok() {
        System.out.println("雷军正在直播");
    }

    @Override
    public void send() {
        System.out.println("卖货 只要999");
    }


    public void self(){
        System.out.println("自身方法");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

测试方法

/**
 * 动态代理模式
 * JDK要求被代理对象必须要有接口
 *
 */
public class MainTest {
    public static void main(String[] args) {
        ManTikTok miTikTok = new MiTikTok();
        ManTikTok proxy = JdkTiktokProxy.getProxy(miTikTok);
        proxy.tiktok();

        System.out.println("---------------");
        SellTiktok sellTikTok = (SellTiktok)miTikTok;
        SellTiktok proxy1 = JdkTiktokProxy.getProxy(sellTikTok);
        proxy1.send(); //只能调用某个接口的实现方法
        System.out.println("---------------");

        MiTikTok miTikTok1 = (MiTikTok) miTikTok;
        //无法代理对象本类自己的方法 proxy只能转成接口类
//        MiTikTok proxy2 = JdkTiktokProxy.getProxy(miTikTok1);
        miTikTok1.self();
        System.out.println(Arrays.asList(miTikTok1.getClass().getInterfaces()));


    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# cglib 动态代理

在 pom.xml 导入 cglib 依赖

    <dependencies>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.1</version>
        </dependency>
    </dependencies>
1
2
3
4
5
6
7

cglib 不依赖于接口代理反射,他会根据代理对象去继承一个新类,从而代理这个对象。

Proxy: 代理主体角色 (代理对象类)

public class CglibProxy {

    //为任意对象创建代理
    public static <T> T crateProxy(T t) {
        //1. 创建一个增强器
        Enhancer enhancer = new Enhancer();
        //2.设置增强哪个类的功能  增强器为这个类动态创建一个子类
        enhancer.setSuperclass(t.getClass());
        //3.设置回调
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method //为了能获取原方法的一些原数据信息
                    , Object[] objects, MethodProxy methodProxy) throws Throwable {
                //编写拦截逻辑
                System.out.println("cglib 代理");

                //当前方法的信息
//                method.getAnnotatedReturnType();
                //目标方法进行执行 原对象的方法
                Object invoke = methodProxy.invokeSuper(o, objects);
                return invoke;
            }
        });

        //创建代理对象
        Object o = enhancer.create();
        return (T)o;

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

RealSubject: 真实主体角色 (被代理对象类)

/**
 * subject 主体
 *
 */
public class MiTikTok  {

    public void self(){
        System.out.println("自身方法");
    }
}
1
2
3
4
5
6
7
8
9
10

测试类

public class CglibTest {
    public static void main(String[] args) {
        //原对象都不用new
        MiTikTok miTikTok = new MiTikTok();
        MiTikTok proxy = CglibProxy.crateProxy(miTikTok);
        proxy.self();
    }
}
1
2
3
4
5
6
7
8

# 应用场景

  • MyBatis 的 mapper 到底是什么?怎么生成的?

    • 动态代理

    • UserMapper、CityMapper,mybatis 帮我们写实现 MapperProxy

  • Alibaba Seata 的 DataSourceProxy 是什么?

  • DruidDataSource 存在的 Proxy 模式

    • 监控链...

几种常见的代理模式介绍 — 几种变体

  1. 防火墙代理:内网通过代理穿透防火墙,实现对公网的访问。
  2. 缓存代理:比如当请求图片文件等资源时,先到缓存代理取,如果取到资源则 ok, 如果取不到资源,再到公网或者数据 库取,然后缓存。
  3. 远程代理:远程对象的本地代表,通过它可以把远程对象当本地对象来调用。远程代理通过网络和真正的远程对象沟通信 息。
  4. 同步代理:主要使用在多线程编程中,完成多线程间同步工作

# 区别 - 装饰器、代理

装饰器、代理:

  • 装饰器和代理之间的区别很细微,可以认为装饰器是代理的一个子集。
  • 静态代理就是装饰器的方式
编辑 (opens new window)
上次更新: 2023/12/13, 06:06:02
装饰器模式(Decorator、Wrapper(包装) Pattern)
外观模式(Facade Pattern)

← 装饰器模式(Decorator、Wrapper(包装) Pattern) 外观模式(Facade Pattern)→

最近更新
01
k8s
06-06
02
进程与线程
03-04
03
计算机操作系统概述
02-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Iekr | Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式