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

Spring之【详解AOP】

目录

前言

定义切面类

registerBeanPostProcessors

一、注册Bean后置处理器,拦截Bean的创建过程

二、使用后置处理器委托执行注册Bean后置处理器的逻辑

三、获取到AnnotationAwareAspectJAutoProxyCreator的beanName

四、创建AnnotationAwareAspectJAutoProxyCreator对象

五、注册AnnotationAwareAspectJAutoProxyCreator

构建Advisors

一、AbstractAutowireCapableBeanFactory的createBean方法中会执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法回调

二、AnnotationAwareAspectJAutoProxyCreator是InstantiationAwareBeanPostProcessor,所以这里会执行到它的postProcessBeforeInstantiation方法(在它的父类AbstractAutoProxyCreator中定义)

三、将增强器放入BeanFactoryAspectJAdvisorsBuilder的advisorsCache集合中

定义一个需要被增强的业务类

创建业务类的代理对象放入单例池中

一、业务类的实例化

二、业务类的初始化

三、Bean后置处理器的初始化后方法回调

四、创建业务类的代理对象

五、放入singletonObjects中的是业务类的代理对象

从容器中获取业务类对象,并执行其添加了@Log注解的方法

一、测试结果

二、通过源码分析其运行流程


前言

  • Spring容器启动时,在AbstractApplicationContext的refresh方法的invokeBeanFactoryPostProcessors这一步骤中执行了ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
  • 该方法会解析到@EnableAspectJAutoProxy注解上的@Import中的value为AspectJAutoProxyRegistrar.class
  • 通过判断得知AspectJAutoProxyRegistrar是ImportBeanDefinitionRegistrar接口的实现类,进而调用到AspectJAutoProxyRegistrar的registerBeanDefinitions方法,将AnnotationAwareAspectJAutoProxyCreator对应的RootBeanDefinition对象放入容器中的beanDefinitionMap集合中
  • AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,它会在AbstractApplicationContext的refresh方法的registerBeanPostProcessors这一步骤中通过beanFactory的getBean方法进行实例化和初始化得到其对象,并存入AbstractBeanFactory的beanPostProcessors集合中
  • 该BeanPostProcessor将会作用于后续其他bean的getBean的流程

定义切面类

  • 自定义注解
package spring.aop;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 该注解只能用在方法上*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}
  • 切面类(切入点+增强逻辑)
package spring.aop;import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;/*** 切面*/
@Aspect
@Component
public class LogAspect {/*** 切入点表达式* 增强有@Log注解的方法*/@Pointcut("@annotation(spring.aop.Log)")public void pointCut() {}/*** 定义前置增强逻辑*/@Before("pointCut()")public void before() {System.out.println("Log...before...");}/*** 定义后置增强逻辑*/@After("pointCut()")public void after() {System.out.println("Log...after...");}
}

registerBeanPostProcessors

一、注册Bean后置处理器,拦截Bean的创建过程

二、使用后置处理器委托执行注册Bean后置处理器的逻辑

三、获取到AnnotationAwareAspectJAutoProxyCreator的beanName

四、创建AnnotationAwareAspectJAutoProxyCreator对象

五、注册AnnotationAwareAspectJAutoProxyCreator

构建Advisors

此时容器中已经有AnnotationAwareAspectJAutoProxyCreator这个后置处理器,它就会作用于接下来Bean的创建过程,在它之后的第一个Bean的getBean过程中,其就会构建Advisors并放入BeanFactoryAspectJAdvisorsBuilder的advisorsCache集合中

一、AbstractAutowireCapableBeanFactory的createBean方法中会执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法回调

二、AnnotationAwareAspectJAutoProxyCreator是InstantiationAwareBeanPostProcessor,所以这里会执行到它的postProcessBeforeInstantiation方法(在它的父类AbstractAutoProxyCreator中定义)

三、将增强器放入BeanFactoryAspectJAdvisorsBuilder的advisorsCache集合中

定义一个需要被增强的业务类

  • 业务类的register方法添加了自定义的@Log注解
package spring.aop;import org.springframework.stereotype.Service;@Service
public class AccountService {/*** 需要被增强的方法*/@Logpublic void register() {System.out.println("AccountService#register...");}
}

创建业务类的代理对象放入单例池中

Bean组件在实例化之后会执行初始化逻辑,初始化逻辑中在执行完初始化方法后会执行BeanPostProcessor的postProcessAfterInitialization方法,也就是会执行AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法

一、业务类的实例化

  • getBean

  • doGetBean

  • createBean

  • doCreateBean

二、业务类的初始化

  • Bean属性填充

  • Bean的初始化逻辑

三、Bean后置处理器的初始化后方法回调

  • 执行AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法

  • 为Bean获取增强逻辑

四、创建业务类的代理对象

  • 根据拿到的增强逻辑createProxy

  • 这里是通过CGLIB创建代理对象

  • 拿到了业务类的代理对象,这里可以看到代理对象中既保存了增强逻辑,同时也保存了目标对象

五、放入singletonObjects中的是业务类的代理对象

  • 执行完AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法(实际定义在其父类中)后返回的是Bean的代理对象

  • 将代理对象放入singletonObjects集合中

从容器中获取业务类对象,并执行其添加了@Log注解的方法

一、测试结果

  • 从容器中获取到的是代理对象
package spring.aop;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AopMain {public static void main(String[] args) {// 容器启动AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);// 从容器中获取业务类对象AccountService accountService = applicationContext.getBean(AccountService.class);// 执行其@Log的方法accountService.register();}
}

  • 执行了增强逻辑

二、通过源码分析其运行流程

  • 开始执行代理对象的方法

  • 执行到CglibAopProxy的intercept方法

  • 获取到目标方法

  • 获取到拦截器链

  • 通过代理对象、目标对象、目标类、目标方法、拦截器链创建ReflectiveMethodInvocation对象

  • 调用proceed方法,currentInterceptorIndex用于记录下标,因为拦截器链是一个List,执行一个可以通过下标++获取下一个

  • 调用MethodInterceptor的invoke方法

  • 拿到前置增强器

  • 执行前置增强逻辑(通过反射调用切面的before方法)

  • 执行目标方法(通过反射调用目标方法)

  • 执行后置增强逻辑(同样是通过反射执行切面类的后置增强逻辑)

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

相关文章:

  • NLP 2025全景指南:从分词到128专家MoE模型,手撕BERT情感分析实战(第四章)
  • scanpy单细胞转录组python教程(三):单样本数据分析之数据标准化、特征选择、细胞周期计算、回归等
  • 制动电阻烧损记录学习
  • Spark执行计划与UI分析
  • JVM调优好用的内存分析工具!
  • jvm有哪些垃圾回收器,实际中如何选择?
  • 工业相机选择规则
  • leetcode经典题目——单调栈
  • 机器学习第八课之K-means聚类算法
  • Android 16 KB页面大小适配的权威技术方案总结
  • Android Camera 打开和拍照APK源码
  • Suno API V5 全面升级——多语言接入,开启 AI 音乐创作新时代
  • GPT‑5 重磅发布
  • 【开源】分层状态机(HFSM)解析:复杂逻辑的清晰表达与FPGA实现(附完整的Verilog交通灯案例及仿真)
  • Loki+Alloy+Grafana构建轻量级的日志分析系统
  • 随机向量正交投影定理(Orthogonal Projection Theorem, OPT)_学习笔记
  • 【YOLO学习笔记】YOLOv11详解
  • Vue 3 快速入门 第五章
  • 强制类型转换
  • 五种 IO 模型与阻塞 IO
  • vscode uv 发布一个python包:编辑、调试与相对路径导包
  • 【代码随想录day 16】 力扣 112. 路径总和
  • printf函数格式化输出攻略
  • SQL(结构化查询语言)的四大核心分类
  • 【Jenkins入门以及安装】
  • 【unitrix数间混合计算】2.11 二进制正整数特质(bin_pos.rs)
  • 《C语言》结构体和联合体练习题--1
  • 如何回收内存对象,有哪些回收算法?
  • Fish shell的abbr命令行参数介绍和Bat文件查看工具
  • 【QT】常⽤控件详解(七)容器类控件 GroupBox TabWidget 布局管理器 Spacer