当前位置:首页 > Java > 正文

深入理解Java代理模式(从静态代理到JDK动态代理实战教程)

在Java开发中,代理模式是一种非常常用的设计模式。它允许你创建一个代理对象来控制对另一个对象的访问。无论你是初学者还是有一定经验的开发者,掌握Java代理模式都能让你写出更灵活、可维护性更高的代码。

什么是代理模式?

代理模式(Proxy Pattern)属于结构型设计模式。它的核心思想是:为其他对象提供一种代理以控制对这个对象的访问。你可以把代理想象成“中间人”——比如你不能直接见某位名人,但可以通过他的经纪人(代理)来沟通。

深入理解Java代理模式(从静态代理到JDK动态代理实战教程) Java代理模式 静态代理 动态代理 JDK动态代理 第1张

代理模式的常见应用场景

  • 远程代理(Remote Proxy):为不同地址空间的对象提供本地代表,如RMI。
  • 虚拟代理(Virtual Proxy):延迟加载大型对象,比如图片懒加载。
  • 保护代理(Protection Proxy):控制对敏感对象的访问权限。
  • 智能引用(Smart Reference):在访问对象时添加额外操作,如记录日志、统计调用次数等。

Java代理模式的两种实现方式

在Java中,代理模式主要分为两类:静态代理动态代理。下面我们分别通过代码示例来学习。

1. 静态代理(Static Proxy)

静态代理是在编译时就确定代理类的。你需要手动编写代理类,并实现与目标对象相同的接口。

步骤一:定义接口

public interface UserService {    void saveUser(String name);}

步骤二:实现真实对象(被代理对象)

public class RealUserService implements UserService {    @Override    public void saveUser(String name) {        System.out.println("正在保存用户: " + name);    }}

步骤三:创建静态代理类

public class StaticUserProxy implements UserService {    private UserService realService;    public StaticUserProxy(UserService realService) {        this.realService = realService;    }    @Override    public void saveUser(String name) {        System.out.println("【代理】开始保存用户前的日志记录...");        realService.saveUser(name);        System.out.println("【代理】用户保存完成!");    }}

测试静态代理:

public class Main {    public static void main(String[] args) {        UserService realService = new RealUserService();        UserService proxy = new StaticUserProxy(realService);        proxy.saveUser("张三");    }}

输出结果:

【代理】开始保存用户前的日志记录...正在保存用户: 张三【代理】用户保存完成!

可以看到,通过静态代理,我们在不修改原业务逻辑的情况下,成功添加了日志功能。

2. 动态代理(Dynamic Proxy)

静态代理虽然简单,但每增加一个接口就需要写一个代理类,维护成本高。于是Java提供了JDK动态代理机制,可以在运行时动态生成代理对象。

注意:JDK动态代理要求目标对象必须实现至少一个接口。

使用InvocationHandler创建通用代理处理器:

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class LogInvocationHandler implements InvocationHandler {    private Object target;    public LogInvocationHandler(Object target) {        this.target = target;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("【动态代理】方法 " + method.getName() + " 开始执行...");        Object result = method.invoke(target, args);        System.out.println("【动态代理】方法 " + method.getName() + " 执行完毕!");        return result;    }}

测试JDK动态代理:

import java.lang.reflect.Proxy;public class DynamicProxyMain {    public static void main(String[] args) {        UserService realService = new RealUserService();                // 创建InvocationHandler        InvocationHandler handler = new LogInvocationHandler(realService);                // 使用Proxy.newProxyInstance动态创建代理对象        UserService proxy = (UserService) Proxy.newProxyInstance(            realService.getClass().getClassLoader(),            realService.getClass().getInterfaces(),            handler        );                proxy.saveUser("李四");    }}

输出结果:

【动态代理】方法 saveUser 开始执行...正在保存用户: 李四【动态代理】方法 saveUser 执行完毕!

通过JDK动态代理,我们只需编写一个通用的InvocationHandler,就能为任意实现了接口的类生成代理,大大提高了代码复用性。

总结

- 静态代理:简单直观,但需要为每个接口编写代理类,适合代理逻辑固定且数量少的场景。

- 动态代理(特别是JDK动态代理):灵活强大,适合需要统一处理多个类的横切关注点(如日志、事务、安全等)。

掌握Java代理模式不仅能帮助你理解Spring AOP等框架的底层原理,还能让你在日常开发中写出更优雅的代码。希望这篇教程能帮助你从零开始掌握代理模式的核心思想与实现方式!