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

【Java】Reflection反射(代理模式)

1、代理模式

        给某个对象提供一个代理对象,并由代理对象来控制其对真实对象的访问。

        Subject(抽象主题角色):定义代理类和真实主题的公告对外方法,通常设计为接口。

        RealSubject(真实主题角色):定义真正的业务实现类。

        Proxy(代理主题角色):用来代理和封装真实主题。

2、静态代理

        代理类在编译时就已经确定,每个目标类都需要对应一个代理类,代码结构相对固定。

public class Client {public static void main(String[] args) {Subject subject = new Proxy();subject.request();}
}
// 代理类(代理主题角色)
class Proxy implements Subject{private Subject target;public Proxy(){target = new RealSubject();}private void before(){System.out.println("开始执行:" + LocalDateTime.now());}@Overridepublic void request() {before();// 代理调用真实主题对象(目标对象)target.request();after();}private void after(){System.out.println("结束执行:" + LocalDateTime.now());}
}
// 目标类(真实主题角色)
class RealSubject implements Subject{@Overridepublic void request() {System.out.println("真实方法被调用,正在执行!!!");try {// 模拟耗时操作Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
// Subject(抽象主题角色)
interface Subject {void request();
}// 结果:
开始执行:2025-07-23T17:58:37.625
真实方法被调用,正在执行!!!
结束执行:2025-07-23T17:58:39.643

3、动态代理

        代理类在运行时动态生成,无需手动编写每个代理类,灵活性更高。Java 中常用的动态代理方式有 JDK 动态代理和 CGLIB 代理。

1、JDK代理

        JDK 动态代理主要涉及两个类:java.lang.reflect.Proxy 和 java.lang.reflect.InvocationHandler 我们通过编写一个调用逻辑处理器 LogHandler 类案例来提供日志增强功能,并实现 InvocationHandler 接口;在 LogHandler 中维护一个目标对象,这个对象是被代理的对象(真实主题角色);在 invoke () 方法中编写方法调用的逻辑处理。

public class Client01 {public static void main(String[] args) {// 真实主题(目标对象)UserServiceImpl userServiceTarget = new UserServiceImpl();// 获取目标对象的类加载器ClassLoader classLoader = userServiceTarget.getClass().getClassLoader();// 获取目标对象的接口列表Class[] interfaces = userServiceTarget.getClass().getInterfaces();// 日志组件(添加额外操作组件相当于Proxy)LogHandler logHandler = new LogHandler(userServiceTarget);// 创建一个代理对象// 参数1:类加载器(目标对象和代理对象的类加载器需要保持一致)// 参数2:抽象主题接口// 参数3:InvocationHandler接口实现类对象(附加行为代码的定义)IUserService userService = (IUserService) Proxy.newProxyInstance(classLoader,interfaces,logHandler);// 调用业务方法userService.select();}
}class LogHandler implements InvocationHandler {private Object target;public LogHandler(Object target){this.target = target;}private void before(){System.out.println("开始执行:" + LocalDateTime.now());}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();Object returnVale = method.invoke(target,args);after();return returnVale;}private void after(){System.out.println("结束执行:" + LocalDateTime.now());}}class UserServiceImpl implements IUserService{@Overridepublic void select() {System.out.println("查询 select");try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}}@Overridepublic void update() {System.out.println("更新 update");}
}interface IUserService {void select();void update();
}// 结果:
开始执行:2025-07-23T18:38:02.468
查询 select
结束执行:2025-07-23T18:38:04.470

        动态代理我们不需要知道自己创建代理类,而是通过方法动态的创建代理对象,从而可以使        其运用更加灵活。

2、CGLIB 代理

        CGLIB是一个强大的、高性能的代码生成库,它允许运行时扩展或者修改类的接口。

        1、无需接口:可以代理灭有实现接口的类。

        2、性能较高:CGLIB使用字节码生成技术,生成代理类的效率要高于Java反射。

        3、方法拦截:通过实现MethodInterceptor接口,可以拦截需要增强的目标类的方法。

       

public class Client02 {public static void main(String[] args) {Enhancer enhancer = new Enhancer();// 设置父类(目标类): cglib基于继承的方式,创建Proxy代理对象enhancer.setSuperclass(UserService.class);// 设置拦截器enhancer.setCallback(new LogHandlerCg());// 创建代理对象UserService userService = (UserService) enhancer.create();// 通过代理对象,调用目标方法userService.select();}
}class LogHandlerCg implements MethodInterceptor{private void before(){System.out.println("开始执行:" + LocalDateTime.now());}private void after(){System.out.println("结束执行:" + LocalDateTime.now());}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {before();Object returnValue = methodProxy.invokeSuper(o,objects);after();return returnValue;}
}class UserService{public void select(){System.out.println("查询 select");}public void update(){System.out.println("更新 update");}
}

4、总结

        代理模式是一种非常实用的设计模式,它通过引入代理对象来控制对目标对象的访问,为系统提供了更强的扩展性和灵活性。静态代理适用于简单场景,而动态代理则更适合复杂多变的场景。

http://www.xdnf.cn/news/16050.html

相关文章:

  • Redis能完全保证数据不丢失吗?
  • Spring Cloud Alibaba Sentinel 基本工作原理源码阅读
  • BQ4050RSMR DIOTEC高精度锂电池保护与电量监测芯片 集成保护+计量+通信
  • AWS Lambda IoT数据处理异常深度分析:从告警到根因的完整排查之路
  • 快手DHPS:国内首个实现基于RDMA 通信的可负载均衡高性能服务架构!
  • 设计汽车集群电源
  • 前端资源缓存优化案例:深入探讨 Nginx 配置中的 Cache-Control 头部叠加问题
  • 一次Oracle集群脑裂问题分析处理
  • 耐达讯自动化EtherCAT转RS232:示波器连接的“开挂秘籍”
  • pig cloud框架中引入websocket
  • Android Camera openCamera
  • Node.js 倒计时图片服务部署与 Nginx 反向代理实战总结
  • OneTwoVLA——基于π0实现类π0.5:一个模型中完成原来双系统下的慢思考、快执行,且具备自适应推理能力和自我纠错能力
  • Java 大视界 -- Java 大数据机器学习模型在电商产品销量预测与库存优化管理中的应用(359)
  • OpenCV 零基础到项目实战 | DAY 2:图像预处理全解析
  • 基于JSP的高校寝室综合管理系统/宿舍管理系统
  • 【JavaSE】正则表达式学习笔记
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 主页-最近七天微博发布量实现
  • PetaLinux 使用技巧与缓存配置
  • Docker 容器中的 HEAD 请求缺失 header?从 Content-MD5 缺失聊起
  • 亚马逊云科技 上海AI研究院 突然解散 | AI早报
  • MatchResult
  • docker-desktop启动失败
  • <PLC><汇川><算法>基于汇川PLC,实现给定数组的“子集求和”算法
  • 技能系统详解(4)——运动表现
  • Day 18:推断聚类后簇的类型
  • 17.VRRP技术
  • rabbitmq 03
  • HTTP 协议常见字段(请求头/响应头)
  • 按键精灵脚本:自动化利刃的双面性 - 从技术原理到深度实践与反思