结构型模式 - 代理模式 (Proxy Pattern)

结构型模式 - 代理模式 (Proxy Pattern)

代理模式是一种结构型设计模式,它允许通过代理对象来控制对另一个对象(目标对象)的访问。代理对象充当目标对象的接口,客户端通过代理对象间接访问目标对象。


分为两大类

  • 静态代理(编译时就知道
  • 动态代理(Java程序运行时才知道

Java 静态代理

java 复制代码
// 定义用户服务接口
public interface UserService {
    // 添加用户方法
    void addUser(String username);
}

// 实现用户服务接口的具体类
public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String username) {
        System.out.println("添加用户: " + username);
    }
}

// 用户服务的代理类
public class UserServiceProxy implements UserService {
    // 持有目标对象
    private UserService target;

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

    @Override
    public void addUser(String username) {
        // 在调用目标方法之前添加额外逻辑,这里是打印日志
        System.out.println("开始添加用户操作,记录日志...");
        // 调用目标对象的方法
        target.addUser(username);
        // 在调用目标方法之后添加额外逻辑,这里是打印日志
        System.out.println("添加用户操作完成,记录日志...");
    }
}

// 测试静态代理的类
public class StaticProxyTest {
    public static void main(String[] args) {
        // 创建目标对象
        UserService target = new UserServiceImpl();
        // 创建代理对象,并将目标对象传入
        UserService proxy = new UserServiceProxy(target);

        // 通过代理对象调用添加用户方法
        proxy.addUser("张三");
        System.out.println();
    }
}

Java 动态代理又细分为两类

  • jdk 代理
  • cglib 代理
java 复制代码
// jdk 方式

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 业务接口
public interface UserService {
    void addUser(String username);
}

// 业务接口实现类
public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String username) {
        System.out.println("添加用户: " + username);
    }
}

// 代理处理器
class UserServiceProxyHandler implements InvocationHandler {
    private final Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用目标方法之前添加额外逻辑
        System.out.println("开始执行添加用户操作...");
        // 调用目标方法
        Object result = method.invoke(target, args);
        // 在调用目标方法之后添加额外逻辑
        System.out.println("添加用户操作执行完毕。");
        return result;
    }
}

// 测试类
public class JdkProxyExample {
    public static void main(String[] args) {
        // 创建目标对象
        UserService target = new UserServiceImpl();
        // 创建代理处理器
        UserServiceProxyHandler handler = new UserServiceProxyHandler(target);
        // 生成代理对象
        UserService proxy = (UserService) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                handler
        );
        // 调用代理对象的方法
        proxy.addUser("张三");
    }
}
java 复制代码
// cglib 代理

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

// 业务类
public class UserManager {
    public void addUser(String username) {
        System.out.println("添加用户: " + username);
    }
}

// 代理拦截器
public class UserManagerInterceptor implements 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;
    }
}

// 测试类
public class CglibProxyExample {
    public static void main(String[] args) {
        // 创建 Enhancer 对象
        Enhancer enhancer = new Enhancer();
        // 设置父类
        enhancer.setSuperclass(UserManager.class);
        // 设置回调函数
        enhancer.setCallback(new UserManagerInterceptor());
        // 生成代理对象
        UserManager proxy = (UserManager) enhancer.create();
        // 调用代理对象的方法
        proxy.addUser("李四");
    }
}

对比分析

根本差异体现

代理机制

  • JDK 代理:依赖接口。在 JDK 代理示例中,UserService 是一个接口,UserServiceImpl 实现了该接口,代理对象是基于接口生成的。
  • CGLIB 代理:基于继承。在 CGLIB 代理示例中,UserManage 是一个普通类,代理对象是 UserManage 的子类。

方法调用

  • JDK 代理:在 InvocationHandler 的 invoke 方法中,使用 method.invoke(target, args) 调用目标对象的方法,这里的 target 是实际的目标对象。
  • CGLIB 代理:在 MethodInterceptor 的 intercept 方法中,使用 proxy.invokeSuper(obj, args) 调用目标类的方法,obj 是代理对象本身。
相关推荐
半夏知半秋4 小时前
游戏登录方案中常见的设计模式整理
服务器·开发语言·笔记·学习·游戏·设计模式·lua
Asort8 小时前
JavaScript设计模式(十八)——备忘录模式:状态保存与恢复的艺术
前端·javascript·设计模式
原来是好奇心8 小时前
告别if-else!使用策略模式优雅处理多种MQTT消息类型
java·mqtt·设计模式·策略模式·emqx
AY呀9 小时前
# 从 HTML5 敲击乐到前端工程化:模块化开发如何重塑交互体验
设计模式
天南星9 小时前
23种设计模式-深度讲解-7. 装饰器模式 (Decorator)
后端·设计模式
hans汉斯10 小时前
【计算机科学与应用】基于多光谱成像与边缘计算的物流安全风险预警模式及系统实现
大数据·数据库·人工智能·设计模式·机器人·边缘计算·论文笔记
杯莫停丶10 小时前
设计模式之:适配器模式
设计模式·适配器模式
xiezhr11 小时前
见过哪些醍醐灌顶的Java代码:从"卧槽"到"原来如此"的顿悟
java·后端·设计模式
WaWaJie_Ngen11 小时前
【设计模式】适配器模式(Adapter)
设计模式·适配器模式
Mr_WangAndy1 天前
C++设计模式_行为型模式_策略模式Strategy
c++·设计模式·策略模式·依赖倒置原则