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

AOP动态代理

文章目录

      • 一、静态代理
      • 二、动态代理底层逻辑
      • 三、基于配置文件的动态代理实现
      • 四、基于注解的动态代理实现
      • 五、@Component和@Ascpect两者结合的意义
        • 示例代码
        • 总结

一、静态代理

  1. 实现方式:定义一个代理类,该类实现与被代理类相同的接口,在代理类中持有被代理类的实例,在实现接口方法时,先执行增强逻辑,再调用被代理类对应的方法。
  2. 测试调用:使用接口类型作为引用,通过“new 代理类(被代理类实例)”的方式创建代理对象,调用接口方法时,会自动执行增强逻辑和被代理类的业务逻辑。
  3. 优点:实现简单,易于理解和上手。
  4. 缺点:
  • 代理类与被代理类耦合度高,若接口发生变化,代理类和被代理类都需要修改。
  • 每个接口都需要对应一个代理类,当存在多个接口时,会产生大量的代理类,增加代码维护成本。

二、动态代理底层逻辑

  1. 基本步骤:
  • 创建被代理类的实例。
  • 创建增强逻辑处理器实例(实现InvocationHandler接口),在其invoke方法中定义增强逻辑和对被代理类方法的调用。
  • 通过Proxy类的newProxyInstance方法生成代理类实例,该方法的参数分别为:被代理类的类加载器、被代理类实现的接口数组、增强逻辑处理器实例。
  1. 核心原理:生成的代理类继承自Proxy类,且实现了被代理类所实现的接口。当调用代理类的方法时,会自动触发增强逻辑处理器的invoke方法,在invoke方法中完成增强逻辑的执行和被代理类方法的调用。

三、基于配置文件的动态代理实现

  1. 配置内容:在配置文件中,通过标签定义被代理类、增强逻辑处理器和代理工厂的实例。
  • 对于被代理类和增强逻辑处理器,设置id作为实例名,class指定对应的类全限定名。
  • 对于代理工厂(如Spring的ProxyFactoryBean),通过property标签配置相关属性,其中target属性引用被代理类实例,interceptorNames属性(以list形式)指定增强逻辑处理器。
  1. 组件扫描:在被代理类、增强逻辑处理器等类上添加@Component注解,以便Spring容器能够扫描并管理这些组件。
  2. 使用方式:通过ApplicationContext加载配置文件,获取代理工厂创建的代理对象,调用接口方法即可触发增强逻辑和业务逻辑。

四、基于注解的动态代理实现

  1. 切面类定义:在类上添加@Component和@Aspect注解,将该类标识为一个切面组件。
  2. 增强逻辑定义:在切面类中,使用@Before、@After、@Around等注解标注方法,这些方法即为增强逻辑(通知),注解的value属性指定切入点表达式,用于确定增强逻辑作用的目标方法。
  3. 代理对象获取:通过ApplicationContext加载配置(通常是通过注解配置开启组件扫描和AOP自动代理),直接从容器中获取被代理类的接口类型实例,该实例实际上是Spring动态生成的代理对象,调用其方法时会自动执行对应的增强逻辑。
  4. 优点:相比配置文件方式,注解方式更加简洁,减少了配置代码,提高了开发效率。

五、@Component和@Ascpect两者结合的意义

当一个类同时被 @Component@Aspect 标注时,意味着:

  1. 该类是 Spring 容器管理的 Bean(通过 @Component);
  2. 该类是一个切面,内部可以定义切入点和通知(通过 @Aspect),用于实现 AOP 功能。
示例代码
// 同时标注 @Component 和 @Aspect,定义一个切面类
@Component
@Aspect
public class LogAspect {// 定义切入点(拦截 com.example.service 包下所有类的所有方法)@Pointcut("execution(* com.example.service.*.*(..))")public void servicePointcut() {}// 定义前置通知(在目标方法执行前执行)@Before("servicePointcut()")public void beforeMethod(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();System.out.println("方法 " + methodName + " 即将执行...");}
}
  • 上述代码中,@Component 确保 LogAspect 被 Spring 实例化;
  • @Aspect 标记它为切面,@Pointcut@Before 则定义了切入点和通知逻辑,实现对目标方法的增强。
总结
  • @Component:让类成为 Spring 管理的 Bean;
  • @Aspect:让类成为切面,用于编写 AOP 逻辑;
  • 两者结合是 Spring 中定义切面类的标准方式,缺一不可(如果只加 @Aspect,Spring 不会管理该类,AOP 逻辑无法生效)。
http://www.xdnf.cn/news/1235773.html

相关文章:

  • #C语言——刷题攻略:牛客编程入门训练(四):运算
  • 大屏项目展示
  • 面向智能体的上下文工程:策略、实现与 LangGraph 实践
  • 09.Redis 常用命令
  • STM32-ESP8266通过MQTT与阿里云通讯
  • Coze 打通飞书多维表格,实现数据增删改查操作实战详解
  • Java线程安全类设计思路总结
  • kafka 是一个怎样的系统?是消息队列(MQ)还是一个分布式流处理平台?
  • RabbitMQ死信队列与消息幂等性实践指南
  • Rust:如何访问 *.ini 配置文件?
  • 关于车位引导及汽车乘梯解决方案的专业性、系统性、可落地性强的综合设计方案与技术实现说明,旨在为现代智慧停车楼提供高效、安全、智能的停车体验。
  • Noob靶场练习
  • 【python实用小脚本-169】『Python』所见即所得 Markdown 编辑器:写完即出网页预览——告别“写完→保存→刷新”三连
  • Rustdesk中继服务器搭建(windows 服务器)
  • SQL注入SQLi-LABS 靶场less31-38详细通关攻略
  • Python篇--- Python 的加载、缓存、覆盖机制
  • (FD Conv)Frequency Dynamic Convolution for Dense Image Prediction论文精读(逐段解析)
  • vscode的Remote-SSH插件配置SSH主机方法
  • 构造类型--结构体,共同体联合体,枚举
  • 知识蒸馏 - 基于KL散度的知识蒸馏 HelloWorld 示例 采用PyTorch 内置函数F.kl_div的实现方式
  • 标记-清除算法中的可达性判定与Chrome DevTools内存分析实践
  • Rust: 获取 MAC 地址方法大全
  • webrtv弱网-QualityScalerResource 源码分析及算法原理
  • 集成电路学习:什么是USB HID人机接口设备
  • Hertzbeat如何配置redis?保存在redis的数据是可读数据
  • PostgreSQL面试题及详细答案120道(21-40)
  • 腾讯人脸识别
  • 14.Redis 哨兵 Sentinel
  • C++中多线程和互斥锁的基本使用
  • [硬件电路-148]:数字电路 - 什么是CMOS电平、TTL电平?还有哪些其他电平标准?发展历史?