资讯详情

资讯详情

反射,动态代理,AOP联系和理解

反射-动态代理-AOP理解反射运行时的“自我审视”能力反射是指程序在运行期间可以获取任意一个类的内部信息如属性、方法、构造器并能够直接操作这些内部成员。核心作用把“类”也当成对象来对待。正常情况下我们通过 new 创建对象有了反射我们可以通过一个字符串类名利用反射 API在运行时动态地创建对象、调用方法。关键类Class、Method、Field、Constructor。生活类比你拿到一个遥控器类的class对象即使不看说明书也能通过按键反射 API试出每个按钮的功能甚至能拆开遥控器看到里面的电路板私有属性。一个简单的反射示例javaClass? clazz Class.forName(“com.example.User”);Object user clazz.newInstance(); // 创建对象Method method clazz.getMethod(“sayHello”);method.invoke(user); // 调用方法动态代理运行时的“替身”机制动态代理是指在程序运行时动态地生成一个代理类这个代理类可以在不修改原目标类代码的情况下对目标类的方法进行增强如添加日志、事务、权限校验、限流逻辑。核心角色目标对象真正执行业务逻辑的对象。代理对象由程序动态生成的“替身”持有目标对象的引用。调用处理器代理对象的所有方法调用都会被转发到这个处理器中由它决定何时调用目标方法、何时添加额外逻辑。两种主流实现JDK 动态代理基于接口。要求目标类必须实现至少一个接口。代理类和目标类实现同一个接口。CGLIB 动态代理基于继承。通过生成目标类的子类来创建代理因此无法代理 final 类或 final 方法。动态代理和反射的关系动态代理是反射最经典的应用场景之一。代理类在运行时正是通过反射来获取目标类的方法并调用 method.invoke(target, args) 来执行目标方法的。AOP面向切面编程的思想AOP 是一种编程思想它把那些与核心业务逻辑无关但被多处业务模块使用的代码如日志、事务、安全抽取出来形成一个的“切面”然后通过注解将这些切面的增强逻辑动态地应用到业务方法上。核心目的解耦。让业务代码只关心业务让通用逻辑切面可以独立维护。核心概念切面通用逻辑的模块化比如一个日志切面。连接点程序执行过程中的一个点比如一个方法的调用。切入点一个表达式用来匹配哪些连接点需要被增强。通知在切入点前后要执行的具体动作如 Before、After、Around。实现方式在 Java 中AOP 的底层实现主要就是动态代理。Spring AOP 就是通过 JDK 或 CGLIB 动态代理在运行时为目标 Bean 生成代理对象从而将切面逻辑“织入”到方法调用中。反射是基石没有反射就无法在运行时动态获取类信息动态代理也就无从谈起。动态代理是反射的应用动态代理利用反射在运行时生成代理类并调用目标方法实现了对方法的无侵入式增强。AOP 是思想动态代理是手段AOP 是一种解耦的编程思想而动态代理是实现这种思想最主流的技术手段。Spring AOP 正是通过动态代理将切面逻辑应用到目标方法上。反射是底层能力动态代理依赖反射创建代理对象AOP是一种编程思想核心是为了将业务和通用逻辑进行解耦依赖动态代理代理对象是转发员本身不干活所有方法调用都转发到调用处理器的 invoke() 方法┌─────────────────────────────────────────────────────────────┐│ 调用方 ││ proxy.sayHello() │└───────────────────────────┬─────────────────────────────────┘│▼┌─────────────────────────────────────────────────────────────┐│ 代理对象 (Proxy) ││ ││ 所有方法调用都被转发不执行真正的业务逻辑 ││ ││ sayHello() → invoke(proxy, sayHello, null) ││ eat() → invoke(proxy, eat, null) ││ pay(100) → invoke(proxy, pay, [100]) │└───────────────────────────┬─────────────────────────────────┘│▼┌─────────────────────────────────────────────────────────────┐│ 调用处理器 (InvocationHandler) ││ ││ invoke(proxy, method, args) { ││ ┌─────────────────────────────────────┐ ││ │ 1. 决定是否调用目标方法 │ ││ │ 2. 决定前置逻辑日志、事务、权限 │ ││ │ 3. method.invoke(target, args) │ ← 反射调用 ││ │ 4. 决定后置逻辑提交、回滚、耗时 │ ││ │ 5. 决定返回值 │ ││ └─────────────────────────────────────┘ ││ } │└───────────────────────────┬─────────────────────────────────┘│▼┌─────────────────────────────────────────────────────────────┐│ 目标对象 (Target) ││ ││ 真正执行 sayHello() 的业务逻辑 ││ 不知道代理和处理器的存在 │└─────────────────────────────────────────────────────────────┘
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →