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

设计模式5-代理模式

定义

        Proxy Partern:为其他对象提供一种代理以控制对这个对象的访问。

目的

         ● 保护原始对象

         ● 解耦合(代理类中增加缓存操作、增加业务逻辑)

场景

  • Collections框架:unmodifiableXXXsynchronizedXXXcheckedXXX

  • RMI:远程方法调用的stub和skeleton

  • Spring框架:AOP、事务管理、安全控制

  • Java EE:EJB、CDI、JPA的延迟加载

  • 数据库连接池:连接管理、资源池化

  • 安全框架:权限检查、访问控制

分类

静态代理

// 接口
interface UserService {void addUser(String name);String getUser(int id);
}// 实现类
class UserServiceImpl implements UserService {public void addUser(String name) {System.out.println("添加用户: " + name);}public String getUser(int id) {return "用户" + id;}
}// 静态代理类
class UserServiceStaticProxy implements UserService {private UserService target;public UserServiceStaticProxy(UserService target) {this.target = target;}public void addUser(String name) {System.out.println("【静态代理】前置处理");target.addUser(name);System.out.println("【静态代理】后置处理");}public String getUser(int id) {System.out.println("【静态代理】前置处理");String result = target.getUser(id);System.out.println("【静态代理】后置处理");return result;}
}

动态代理

JDK动态代理

        JDK动态代理是Java标准库内置的代理实现,基于接口的代理。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;//集合只读类
public class JDKProxyExamples {// 创建只读List的代理public static <T> List<T> createReadOnlyList(List<T> originalList) {return (List<T>) Proxy.newProxyInstance(originalList.getClass().getClassLoader(),originalList.getClass().getInterfaces(),new ReadOnlyInvocationHandler(originalList));}static class ReadOnlyInvocationHandler implements InvocationHandler {private final Object target;public ReadOnlyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String methodName = method.getName();// 拦截修改操作if (methodName.startsWith("add") || methodName.startsWith("remove") || methodName.startsWith("set") || methodName.startsWith("clear")) {throw new UnsupportedOperationException("只读集合,不支持修改操作");}// 允许读操作return method.invoke(target, args);}}public static void main(String[] args) {List<String> originalList = new ArrayList<>();originalList.add("Java");originalList.add("Python");originalList.add("C++");List<String> readOnlyList = createReadOnlyList(originalList);System.out.println("原始列表: " + originalList);System.out.println("只读代理列表: " + readOnlyList);// 读操作正常System.out.println("第一个元素: " + readOnlyList.get(0));System.out.println("列表大小: " + readOnlyList.size());try {// 写操作会抛出异常readOnlyList.add("JavaScript");} catch (Exception e) {System.out.println("写操作异常: " + e.getMessage());}}
}

CGLIB动态代理

        基于cglib库来实现(非jdk原生),需要引入第三方类库

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;/*** CGLIB方法拦截器
*  添加maven依赖
* MAVEN download sources下即可
* <dependencies>
*     <dependency>
*         <groupId>cglib</groupId>
*         <artifactId>cglib</artifactId>
*         <version>3.3.0</version>
*     </dependency>
* </dependencies>*/
public class CglibMethodInterceptor implements MethodInterceptor {private Object target;public CglibMethodInterceptor(Object target) {this.target = target;}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {String methodName = method.getName();// 过滤掉Object类的方法(如toString, hashCode等)if (Object.class.equals(method.getDeclaringClass())) {return proxy.invokeSuper(obj, args);}// 过滤final方法和static方法if (methodName.equals("getServiceInfo") || methodName.equals("getVersion")) {System.out.println("【CGLIB】跳过final/static方法: " + methodName);return method.invoke(target, args);}System.out.println("【CGLIB代理】前置处理 - 方法: " + methodName);try {// 调用目标方法Object result = proxy.invoke(target, args);System.out.println("【CGLIB代理】后置处理 - 方法: " + methodName + ", 结果: " + result);return result;} catch (Exception e) {System.out.println("【CGLIB代理】异常处理 - 方法: " + methodName + ", 异常: " + e.getMessage());throw e;} finally {System.out.println("【CGLIB代理】最终处理 - 方法: " + methodName);}}
}/*** CGLIB代理工厂*/
class CglibProxyFactory {/*** 创建代理对象(使用默认构造函数)*/public static <T> T createProxy(Class<T> targetClass) {return createProxy(targetClass, null, null);}/*** 创建代理对象(带参数)*/public static <T> T createProxy(Class<T> targetClass, Class<?>[] argumentTypes, Object[] arguments) {Enhancer enhancer = new Enhancer();// 设置父类(被代理的类)enhancer.setSuperclass(targetClass);// 设置回调拦截器enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("【CGLIB通用代理】方法调用: " + method.getName());return proxy.invokeSuper(obj, args);}});// 创建代理对象if (argumentTypes != null && arguments != null) {return (T) enhancer.create(argumentTypes, arguments);} else {return (T) enhancer.create();}}/*** 创建带有自定义拦截器的代理对象*/public static <T> T createProxyWithInterceptor(Class<T> targetClass, MethodInterceptor interceptor) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(targetClass);enhancer.setCallback(interceptor);return (T) enhancer.create();}
}

对比

特性静态代理JDK动态代理CGLIB动态代理
实现方式手动编写代理类基于接口,使用ProxyInvocationHandler基于继承,使用字节码技术
依赖无特殊依赖Java标准库需要cglib库依赖
目标要求需要接口或具体类必须基于接口可以代理具体类(无需接口)
性能较高(直接调用)中等(反射调用)较高(方法索引调用)
生成方式编译时生成运行时生成代理类运行时生成子类
方法拦截硬编码在代理类中通过InvocationHandler统一处理通过MethodInterceptor统一处理
final方法可以代理可以代理(通过接口)无法代理(final方法不能重写)
构造函数可自定义只能使用无参构造可处理有参构造
使用复杂度高(每个类需要单独代理)中(统一处理逻辑)中(统一处理逻辑)
代码示例需要为每个接口写实现使用Proxy.newProxyInstance()使用Enhancer.create()

实例

房东(House)、租客(Client)、中介(Proxy)

        假如你是一个房东,不想与租客进行打交道,这时候可以代理给中介(proxy)让中介处理租房事宜,房东只需要根据中介打交道即可。

import java.util.HashMap;
import java.util.Map;// 抽象主题接口
interface RentalService {void rentHouse(String clientName, Map<String, Object> houseDetails);Map<String, Object> showHouse(String houseId);
}// 真实主题:房东
class HouseOwner implements RentalService {private Map<String, Map<String, Object>> houses;public HouseOwner() {houses = new HashMap<>();Map<String, Object> house1 = new HashMap<>();house1.put("location", "市中心");house1.put("price", 3000);house1.put("size", "80平米");Map<String, Object> house2 = new HashMap<>();house2.put("location", "郊区");house2.put("price", 2000);house2.put("size", "100平米");houses.put("001", house1);houses.put("002", house2);}@Overridepublic void rentHouse(String clientName, Map<String, Object> houseDetails) {System.out.println("房东直接与" + clientName + "签订合同,租赁" + houseDetails.get("location") + "的房屋");System.out.println("月租: " + houseDetails.get("price") + "元, 面积: " + houseDetails.get("size"));}@Overridepublic Map<String, Object> showHouse(String houseId) {return houses.get(houseId);}
}// 代理:中介
class HouseAgent implements RentalService {private HouseOwner houseOwner;private double commissionRate = 0.1;public HouseAgent(HouseOwner houseOwner) {this.houseOwner = houseOwner;}@Overridepublic Map<String, Object> showHouse(String houseId) {System.out.println("中介带看房屋" + houseId);return houseOwner.showHouse(houseId);}@Overridepublic void rentHouse(String clientName, Map<String, Object> houseDetails) {// 中介添加额外服务System.out.println("中介为" + clientName + "提供专业咨询服务");System.out.println("中介协助" + clientName + "检查房屋状况");// 计算中介费int price = (Integer) houseDetails.get("price");double commission = price * commissionRate;System.out.println("中介代表房东与" + clientName + "签订合同");System.out.println("租赁" + houseDetails.get("location") + "的房屋");System.out.println("月租: " + price + "元, 中介费: " + commission + "元/月, 面积: " + houseDetails.get("size"));// 实际调用房东的租赁方法houseOwner.rentHouse(clientName, houseDetails);}
}// 客户端:租客
class Tenant {private String name;public Tenant(String name) {this.name = name;}public void findHouseThroughAgent(HouseAgent agent, String houseId) {System.out.println(name + "通过中介寻找房屋");Map<String, Object> houseDetails = agent.showHouse(houseId);if (houseDetails != null) {agent.rentHouse(name, houseDetails);} else {System.out.println("未找到合适的房屋");}}public void findHouseDirectly(HouseOwner houseOwner, String houseId) {System.out.println(name + "直接联系房东寻找房屋");Map<String, Object> houseDetails = houseOwner.showHouse(houseId);if (houseDetails != null) {houseOwner.rentHouse(name, houseDetails);} else {System.out.println("未找到合适的房屋");}}
}// 使用示例
public class ProxyPatternExample {public static void main(String[] args) {// 创建房东HouseOwner houseOwner = new HouseOwner();// 创建中介(代理)HouseAgent agent = new HouseAgent(houseOwner);// 创建租客Tenant tenant = new Tenant("张三");System.out.println("=== 租客通过中介租房 ===");tenant.findHouseThroughAgent(agent, "001");System.out.println("\n=== 租客直接联系房东租房 ===");tenant.findHouseDirectly(houseOwner, "002");}
}

代理模式代码

http://www.dtcms.com/a/349643.html

相关文章:

  • 无锁队列的设计与实现
  • jdbc相关内容
  • 基于TimeMixer的帕金森语音分类:WAV音频输入与训练全流程
  • 基于开源 AI 智能名片链动 2+1 模式 S2B2C 商城小程序的新开非连锁品牌店开业引流策略研究
  • 云计算之中间件与数据库
  • 蜂窝物联网模组在冷链运输行业的应用价值
  • 盲盒经济新风口:盲盒抽谷机小程序系统开发全解析
  • 审核问题——首次进入APP展示隐私政策弹窗
  • JavaWeb(八)EL表达式,JSTL标签
  • 阿里云短信验证码服务
  • 奔赴少年CIIU携专辑《我们的出发》正式出道 与J.Y. Park同台首秀备受关注
  • 基于SpringBoot的招聘管理系统【2026最新】
  • 【Linux基础知识系列】第一百一十篇 - 使用Nmap进行网络安全扫描
  • C# NX二次开发:绘图区控件和指定矢量控件详解
  • [MH22D3开发笔记]2. SPI,QSPI速度究竟能跑多快,双屏系统的理想选择
  • 基于WebTransport(底层QUIC)实现视频传输(HTML+JavaScript)
  • C语言基础:(二十五)预处理详解
  • 从0到1:用 Qwen3-Coder 和 高德MCP 助力数字文旅建造——国庆山西游
  • Rust面试题及详细答案120道(58-65)-- 集合类型
  • 解锁处暑健康生活
  • Docker:部署Nginx
  • week4-[一维数组]数码个数
  • Gemini 2.5 Flash-Lite 与 GPT-5-mini:高性能低成本模型,如何选择?
  • 链表OJ习题(1)
  • redis-缓存-持久化
  • 使用 Gemini CLI作为 Claude Code的 subagent
  • OC-MVC模式下的折叠cell
  • 利用 Python 爬虫获取 1688 商品详情 API 返回值说明(代码示例)实战指南
  • 爬虫基础学习-爬取网页项目
  • vue2使用WaveSurfer实现简易的音频播放