1097 字
约 3 分钟
2
代理设计模式(Proxy Pattern)

代理设计模式(Proxy Pattern)

1. 什么是代理模式?

代理模式:不直接访问目标对象,而是通过代理对象间接访问目标对象,由代理对象控制目标方法的执行逻辑。

简单理解:

原本应该由目标对象完成的事情,交给代理对象处理,代理可以在调用目标方法前后增加额外逻辑。


2. 现实例子

张三想买房,但是:

  • 不懂房产市场
  • 不知道如何找房
  • 不懂交易流程

于是找到房产中介。

流程:

张三
 |
 | 委托买房
 ↓
中介(代理)
 |
 | 看房
 | 谈价格
 | 办手续
 ↓
完成购房

张三只需要和中介沟通,不需要关心背后的找房、谈判、手续流程。

这就是代理:

隐藏复杂流程,让调用方只关注自己的目标。


3. Java 中的代理

例如 Mybatis:

我们平时写:

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

mapper.findUser();

看起来只是调用 Mapper 方法。

但是实际上 Mybatis 在背后完成:

Mapper代理对象
        |
        ↓
解析方法
        |
        ↓
生成SQL
        |
        ↓
获取数据库连接
        |
        ↓
执行SQL
        |
        ↓
封装返回结果

开发者不需要关注 JDBC 的细节。


4. CGLIB 动态代理示例

引入依赖:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

代码:

import net.sf.cglib.proxy.*;

import java.lang.reflect.Method;


public class CGLibProxyDemo {

    public static void main(String[] args) {

        HelloTarget target = new HelloTarget();


        Enhancer enhancer = new Enhancer();

        // 代理目标类
        enhancer.setSuperclass(HelloTarget.class);


        // 设置代理逻辑
        enhancer.setCallback(new MethodInterceptor() {

            @Override
            public Object intercept(
                    Object obj,
                    Method method,
                    Object[] args,
                    MethodProxy proxy
            ) throws Throwable {


                System.out.println("方法执行前");


                // 调用目标方法
                Object result = proxy.invokeSuper(obj, args);


                System.out.println("方法执行后");


                return result;
            }
        });


        // 创建代理对象
        HelloTarget proxy =
                (HelloTarget) enhancer.create();


        // 调用代理方法
        proxy.sayHello();
    }
}


class HelloTarget {

    public void sayHello() {

        System.out.println("Hello World");

    }
}

执行结果:

方法执行前

Hello World

方法执行后

5. 两个重要方法区别

proxy.invokeSuper()

调用:

代理对象
   |
   ↓
目标对象方法

也就是:

执行真正的目标方法。

例如:

proxy.invokeSuper(obj,args);

相当于:

target.sayHello();

proxy.invoke()

调用:

代理对象
   |
   ↓
代理方法
   |
   ↓
再次进入 intercept()

容易产生:

intercept()
    |
    ↓
invoke()
    |
    ↓
intercept()
    |
    ↓
invoke()
    |
    ↓
无限循环

最终导致:

StackOverflowError

所以 CGLIB 中调用目标方法通常使用:

proxy.invokeSuper()

6. 代理可以做什么?

代理最大的作用:

① 方法增强

在目标方法前后增加逻辑。

例如:

开始事务

执行方法

提交事务

② 异常处理

例如:

调用方法

如果异常:

记录日志
发送报警
回滚事务

③ 修改返回结果

例如:

目标方法返回数据

代理进行包装

返回新的数据

7. 常见应用场景

AOP

Spring AOP 本质就是代理。

例如:

@Transactional
public void saveUser(){

}

执行:

代理对象

开启事务

调用saveUser()

提交事务

开发者不用手动写事务代码。


Mybatis

Mapper 接口本身没有实现类。

例如:

userMapper.selectById(1);

实际调用:

Mapper代理对象

↓

SqlSession

↓

执行SQL

↓

返回结果

RPC

RPC 调用:

userService.getUser();

看起来像调用本地方法。

实际:

客户端代理

↓

封装请求

↓

序列化

↓

网络传输

↓

服务发现

↓

负载均衡

↓

调用远程服务

↓

返回结果

这些过程用户完全不知道。


8. 总结

代理模式核心:

① 屏蔽复杂实现

让调用者只关注业务:

调用方法

而不用关心:

连接
解析
网络
事务
日志
权限

② 增强目标方法

代理可以在目标方法:

  • 执行前
  • 执行后
  • 出异常时
  • 返回结果时

增加额外逻辑。

一句话总结:

代理模式就是通过代理对象控制目标对象的访问,并在不修改目标代码的情况下增强目标方法。

代理设计模式(Proxy Pattern)
http://clxhxhhr.top/posts/376/
作者
clxstart
发布于
2026-09-01
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。