Spring生命周期中织入代理逻辑

article/2025/7/13 2:13:22

在Spring生命周期中织入代理逻辑

    • 一,AOP 自动代理的实现机制
      • 如何判断某个 Bean 是否需要被代理?
      • 代理对象在哪个生命周期节点创建?
    • 二,底层实现逻辑
      • 1,自动代理的实现
        • 实例化AwareBeanPostProcessor
        • SmartInstantiationAwareBeanPostProcessor
        • 抽象自动代理创建者
        • 抽象顾问自动代理创建器
          • wrapIfNecessary:判断是否创建代理并包装
        • 默认顾问自动代理创建者
      • 2,融入BeanFactory
        • AbstractAutowireCapableBeanFactory 增强

源码见:mini-spring

在这里插入图片描述

一,AOP 自动代理的实现机制

在手写 AOP 框架或者理解 Spring AOP 的底层实现时,一个关键问题是:代理对象是如何在 Spring 生命周期中被创建的?

AOP 的“自动代理”本质上是将代理对象的创建融入到 Spring 的 Bean 生命周期中。在 createBean 的流程中,Spring 会判断当前 Bean 是否需要被增强(即是否是一个代理对象),如果是,就会绕过原始 Bean 的常规实例化流程,直接返回一个代理对象。

如何判断某个 Bean 是否需要被代理?

前面我们已经将切点(Pointcut)和通知(Advice)封装成了一个个完整的 Advisor 对象。每个 Advisor 内部都包含了一个 Pointcut,而我们可以通过 Pointcut 的 matches 方法来判断某个类是否匹配某个增强逻辑。

也就是说,在 Bean 创建过程中,框架可以遍历已有的 Advisor,通过匹配机制识别哪些类是“待增强对象”,并据此决定是否创建代理。

代理对象在哪个生命周期节点创建?

这是自动代理实现的关键:是在 postProcessBeforeInitialization 还是 postProcessAfterInitialization 中创建代理?

  • postProcessBeforeInitialization:此时 Bean 已被实例化,但还未完成依赖注入。如果此时直接返回代理对象,将中断后续的注入与初始化流程。因此,一般不在此阶段生成代理。

  • postProcessAfterInitialization:这是最常见的切入点。Bean 已完成实例化、属性注入与初始化,此时创建代理对象并返回,不会影响原有的生命周期流程

当然,Spring 并非绝对依赖后置增强。例如,对于某些自定义的 TargetSource(例如热部署场景中),Spring 允许用户在前置处理阶段就接管整个 Bean 的创建与生命周期管理。

二,底层实现逻辑

1,自动代理的实现

我们当前实现的是基础的 AOP 自动代理机制,尚未处理代理的循环依赖与代理链问题,这部分将在后续章节中进一步探讨。 相关代码可参考项目的 Git 提交记录。

实例化AwareBeanPostProcessor

定义用于 Bean 实例化前处理的接口,用于实现自动代理逻辑的扩展点。

定义用于初始化的InstantiationAwareBeanPostProcessor接口,实现BeanPostProcessor,用于后续的代理增强逻辑等

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor{  Object postProcessBeforeInstantiation(Class<?> beanClass , String beanName);  }
SmartInstantiationAwareBeanPostProcessor

用于支持更复杂的场景(如循环依赖的代理处理),当前版本暂未使用,后续会补充。

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor{  
}

这些接口是为了更好地与 Spring 的架构体系对接。 目前只需关注核心实现类 。AbstractAdvisorAutoProxyCreator

抽象自动代理创建者

AbstractAutoProxyCreator 是自动代理的抽象基类,实现了 和 接口。 其职责是为目标 Bean 提供统一的自动代理创建逻辑,封装了创建代理对象的基础流程。SmartInstantiationAwareBeanPostProcessor``BeanFactoryAware

/**  * 抽象自动代理创建器类  * 该类实现了SmartInstantiationAwareBeanPostProcessor和BeanFactoryAware接口,  * 用于自动创建代理 bean,其主要作用是简化AOP(面向切面编程)的配置和使用  *  * @author jixu * @title AbstractAutoProxyCreator * @date 2025/5/29 00:44 */
public abstract class AbstractAutoProxyCreator implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {  }
抽象顾问自动代理创建器

这是自动代理的核心类,实现了创建代理对象的完整流程:

  • 它在 中调用 方法,决定是否为某个 Bean 创建代理。postProcessAfterInitialization``wrapIfNecessary

  • 代理判断依据为:是否匹配某个切面(通过 判断)。AspectJExpressionPointcutAdvisor

关键方法如下:

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {return wrapIfNecessary(bean, beanName);
}
wrapIfNecessary:判断是否创建代理并包装

该方法核心逻辑:

  1. 跳过基础设施类(如 Advisor、Pointcut 等)

  2. 获取所有 Advisor

  3. 遍历判断当前 Bean 是否匹配某切点

  4. 若匹配,使用 创建代理对象并返回ProxyFactory

/**  * 抽象的顾问自动代理创建者类  * 该类的作用是自动创建代理对象,根据特定的规则或条件,动态地应用顾问(Advisor)到目标对象上  * 主要用于Spring框架的AOP(面向切面编程)功能中,以实现自动代理机制  *  * @author jixu * @title AbstractAdvisorAutoProxyCreator * @date 2025/5/29 00:44 */
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator{  // 定义一个 BeanFactory 属性,用于管理 Bean 的创建和生命周期。  private DefaultListableBeanFactory beanFactory;  /**  * 设置 BeanFactory。  * 当本类需要访问或操作 Spring 容器中的 Bean 时,通过此方法注入 BeanFactory。  *  * @param beanFactory Spring 容器的 BeanFactory。  */  @Override  public void setBeanFactory(BeanFactory beanFactory) {  this.beanFactory = (DefaultListableBeanFactory) beanFactory;  }  /**  * 在 Bean 实例化之前进行后处理。  * 用于创建自定义 TargetSource代理对象  * 跳过默认生命周期:直接返回代理对象后,Spring 会跳过该 Bean 的默认实例化、依赖注入和初始化流程,由代理完全控制目标对象的行为。  *  * @param beanClass Bean 的类。  * @param beanName  Bean 的名称。  * @return 返回代理对象,如果没有代理则返回 null。  */  @Override  public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {  return null;  }  /**  * 判断指定的类是否是基础设施类。  * 基础设施类包括 Advice、Pointcut 和 Advisor 类,这些类用于 AOP 的配置和实现。  *  * @param beanClass 要判断的类。  * @return 如果是基础设施类则返回 true,否则返回 false。  */  private boolean isInfrastructureClass(Class<?> beanClass) {  return Advice.class.isAssignableFrom(beanClass)  || PointCut.class.isAssignableFrom(beanClass)  || Advisor.class.isAssignableFrom(beanClass);  }  /**  * 在 Bean 初始化之前执行自定义处理逻辑。  * 使用此方法,可以在 Bean 被初始化之前对其进行修改或执行其他操作。  *  * @param bean     当前正在初始化的 Bean 实例。  * @param beanName 当前 Bean 的名称。  * @return 返回处理后的 Bean 实例,可以是原始 Bean 或修改后的 Bean。  */  @Override  public Object postProcessBeforeInitialization(Object bean, String beanName) {  return bean;  }  /**  * 在 Bean 初始化之后执行自定义处理逻辑。  * 使用此方法,可以在 Bean 初始化完成后对其进行进一步的修改或执行其他操作。  *  * @param bean     当前已经初始化的 Bean 实例。  * @param beanName 当前 Bean 的名称。  * @return 返回处理后的 Bean 实例,可以是原始 Bean 或修改后的 Bean。  */  @Override  public Object postProcessAfterInitialization(Object bean, String beanName) {  return wrapIfNecessary(bean, beanName);  }  /**  * 根据需要包装 Bean。  * 如果 Bean 需要被代理,则创建并返回代理对象;否则返回原始 Bean。  *  * @param bean     当前 Bean 实例。  * @param beanName 当前 Bean 的名称。  * @return 返回可能被包装过的 Bean 实例。  */  protected Object wrapIfNecessary(Object bean, String beanName){  Class<?> beanClass = bean.getClass();  // 避免代理AOP相关配置类  if (isInfrastructureClass(beanClass)) {  return null;  }  // 获取到所有的Advisor  Collection<AspectJExpressionPointcutAdvisor> advisors = beanFactory.getBeanOfType(AspectJExpressionPointcutAdvisor.class).values();  try {  for (AspectJExpressionPointcutAdvisor advisor : advisors) {  // 如果要代理的是当前类  if (advisor.getPointcut().getClassFilter().matches(beanClass)) {  AdvisedSupper advisedSupper = new AdvisedSupper();  BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);  Object beanInstantiate = beanFactory.getInstantiationStrategy().instantiate(beanDefinition);  TargetSource targetSource = new TargetSource(beanInstantiate);  advisedSupper.setMethodInterceptor(((MethodInterceptor) advisor.getAdvice()));  advisedSupper.setTargetSource(targetSource);  advisedSupper.setMethodMatcher(advisor.getPointcut().getMethodMatcher());  Object proxy = new ProxyFactory(advisedSupper).getProxy();  return proxy;  }  }  } catch (Exception e) {  throw new BeansException("代理对象:"+beanName+"创建失败", e);  }  return bean;  }  
}
默认顾问自动代理创建者

该类作为最终对外暴露的默认实现,继承自 ,无新增逻辑,仅作为注册入口。AbstractAdvisorAutoProxyCreator

/**  * DefaultAdvisorAutoProxyCreator类的作用是自动创建代理Bean,该类主要负责根据Advisor来创建代理Bean,  * 并将这些Bean自动应用到应用程序上下文中。它实现了BeanPostProcessor接口,以便在Bean创建前后进行处理,  * 并使用AopProxyFactory来创建代理对象。该类还支持通过设置暴露代理属性来控制是否将代理Bean暴露给其他Bean使用。  *  * @author jixu * @title DefaultAdvisorAutoProxyCreator * @date 2025/5/28 15:48 */public class DefaultAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator  {  }

2,融入BeanFactory

#AbstractAutowireCapableBeanFactory

为了使自动代理能够生效,我们需要在 Bean 实例化流程中注入代理创建逻辑。

AbstractAutowireCapableBeanFactory 增强

重写 方法,在实例化前调用自动代理扩展点:createBean

@Override  
protected Object createBean(String beanName, BeanDefinition beanDefinition) {  try {  // 给 BeanPostProcessors 一个返回代理而不是目标 bean 实例的机会。  Object bean = resolveBeforeInstantiation(beanName, beanDefinition);  if (bean != null) {  return bean;  }  } catch (Throwable ex) {  throw new BeansException("BeanPostProcessor before instantiation of bean failed", ex);  }return doCreateBean(beanName , beanDefinition);  
}

resolveBeforeInstantiation:提前触发代理创建

/**  * 在实例化之前解析Bean  * 如果Bean是代理对象,提前执行beanPostProcessor逻辑  *  * @param beanName Bean名称  * @param beanDefinition Bean的定义信息  * @return 如果是代理对象,则返回处理后的Bean实例,否则返回null  */
protected Object resolveBeforeInstantiation(String beanName, BeanDefinition beanDefinition) {  // 判断当前Bean是否为代理对象,提前执行beanPostProcessor逻辑  Object bean = applyBeanPostProcessorsBeforeInstantiation(beanDefinition.getBeanClass(), beanName);  if (bean != null){  bean = applyBeanPostProcessorsAfterInitialization(bean,beanName);  }  return bean;  
}

applyBeanPostProcessorsBeforeInstantiation:触发前置处理

/**  * 在实例化之前应用BeanPostProcessor  * * @param beanClass Bean的类  * @param beanName Bean的名称  * @return 如果Bean是代理对象,则返回处理后的Bean实例,否则返回null  */private Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName) {  // 获取到所有的BeanPostProcess  List<BeanPostProcessor> beanPostProcessors = getBeanPostProcessors();  // 筛选出InstantiationAwareBeanPostProcessor类型的beanPostProcessor  for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {  if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor){  // 如果前置增强执行成功返回到的Bean非空则说明该Bean是被代理Bean  Object bean = ((InstantiationAwareBeanPostProcessor) beanPostProcessor).postProcessBeforeInstantiation(beanClass, beanName);  if (bean != null){  return bean;  }  }  }  return null;  
}

http://www.hkcw.cn/article/lVLihSBfpy.shtml

相关文章

参数化建模(三):SOLIDWORKS中的参数化应用实例

在现代工程设计领域&#xff0c;参数化设计已成为提升设计效率、优化产品性能、实现智能制造的重要手段。尤其是在三维建模软件SOLIDWORKS中&#xff0c;参数化设计的理念和方法被广泛应用&#xff0c;极大地推动了机械、建筑、电子等行业的创新发展。 那么&#xff0c;什么是…

STM32G4 电机外设篇(二) VOFA + ADC + OPAMP

目录 一、STM32G4 电机外设篇&#xff08;二&#xff09; VOFA ADC OPAMP1 VOFA1.1 VOFA上位机显示波形 2 ADC2.1 用ADC规则组对板载电压和电位器进行采样 3 OPAMP&#xff08;运放&#xff09;3.1 结合STM32内部运放和ADC来完成对三相电流的采样3.2 运放电路分析 附学习参考…

KVM 安装 Ubuntu 22

在 KVM 中安装 Ubuntu 22 虚拟机。 首先创建硬盘文件 sudo qemu-img create -f qcow2 /app/vms/ubuntu22.qcow2 100G安装Ubuntu 22 sudo virt-install \--name ubuntu22 \--ram 4096 \--vcpus 2 \--disk path/app/vms/ubuntu22.qcow2,formatqcow2 \--os-type linux \--os-va…

【Python】第二弹:搭建 Python 环境

目录 一、安装 Python 第一步:找到官方网站 第二步:找到下载页面 第三步:双击安装包 第四步:运行 hello world 二、安装 PyCharm 第一步:找到官方网站 第二步:找到下载页面 第三步:双击安装包 第四步:运行 hello world 三、PyCharm 基本设置 3.1 设置字体大…

城市内涝精准监测・智能预警・高效应对:治理方案解析

城市化进程加速与极端天气频发叠加&#xff0c;城市内涝对城市安全运行和居民生活的威胁日益凸显。多地频发的强降雨引发严重内涝&#xff0c;"看海"现象、交通瘫痪及财产损失等问题&#xff0c;暴露出传统内涝防治体系在监测精准度、预警及时性和应对高效性上的不足…

解决RAGFlow(v0.19.0)有部分PDF无法解析成功的问题。

ragflow版本为&#xff1a;v0.19.0 1.解析的时候报错&#xff1a;Internal server error while chunking: Coordinate lower is less than upper。 看报错怀疑是分片的问题&#xff0c;于是把文档的切片方法中的“建议文本块大小”数值&#xff08;默认512&#xff09;调小&…

IoTDB 集成 DBeaver,简易操作实现时序数据清晰管理

数据结构一目了然&#xff0c;跨库分析轻松实现&#xff0c;方便 IoTDB “内部构造”管理&#xff01; 随着物联网场景对时序数据处理需求激增&#xff0c;时序数据库与数据库管理工具的集成尤为关键。作为数据资产的 “智能管家”&#xff0c;借助数据库管理工具的可视化操作界…

比较二维结构的尺寸分布

在行列可自由变换的平面上5点结构有34个 其中尺寸在3*3范围内的有7个 在4*4范围内的有14个 在5*5范围内的有13个 现在假设平面上有5个不可分辨的点在随机的运动&#xff0c;这5个点可能的位置关系就只有这34种。现在假设点与点之间的距离是稳定不变的的,且每个状态只出现一次。…

WSL里执行python深度学习的一些方法记录

安装anaconda3&#xff1a; 可以直接从 Download Now | Anaconda 中下载&#xff0c;然后拷贝到WSL环境的某个目录&#xff0c;执行 bash xxxxxxx.sh 即可安装。 启动jupyter notebook&#xff1a; 先conda activate 当前环境&#xff0c;然后pip install jupyter 此时&am…

防爆组合式智能全温振荡防爆培养箱,守护安全场所

品牌&#xff1a;宇晶峰 型号&#xff1a;BGZ-929PY-03ZC 使用温度&#xff1a;4~60C 温度分辨率/波动度/分布精度&#xff1a;0.1C/0.5C/1C(38C时) 回旋幅度/回旋频率范围(r/min&#xff09;&#xff1a;Φ26mm(选配Φ50mm)/30~300(选配5~400) 回旋频率…

如何选择适合的冲压件清洗机?冲压件清洗机的选购指南

冲压件清洗机是工业生产中不可或缺的设备之一&#xff0c;主要用于去除冲压过程中产生的油污、灰尘、碎屑等污染物&#xff0c;确保冲压件的清洁度和质量。适当选择合适的冲压件清洗机对于提高生产效率、降低成本以及保证产品质量都具有重要意义。以下是一份关于如何选择适合的…

2023-2024-2-《移动机器人设计与实践》上机测评

2022-2023-2-移动机器人设计与实践-期末A-CSDN博客 2022-2023-2-移动机器人设计与实践-期末B-CSDN博客 理论和实践分开测评&#xff0c;如下是实践部分 摘要&#xff1a; 《移动机器人设计与实践》期末上机测评要求学生完成配置题和实践题两部分。配置题&#xff08;30分&am…

[HNCTF 2022 Week1]silly_zip

下载附件 解压发现需要密码 用010打开看看&#xff0c;发现是伪加密 改成00点击保存 解压后得到图片 感觉图片看着怪怪的&#xff0c;修改一下高度看看有没有其他线索 把47改成78 最后得到flag

QSS 的选择器

1. 样式表规则 样式表包含了一系列的样式规则&#xff0c;每个样式规则由选择器&#xff08;selector&#xff09;和声明&#xff08;declaration&#xff09;组成。     选择器&#xff1a;指定了受该规则影响的部件。     声明&#xff1a;指定了这个部件上要设置的属性。…

Python 训练营打卡 Day 30-模块和库的导入

模块和库的导入 1.1标准导入 import mathprint("方式1: 使用 import math") print(f"圆周率π的值: {math.pi}") print(f"2的平方根: {math.sqrt(2)}\n") 1.2从库中导入特定项 from math import pi, sqrtprint("方式2&#xff1a;使用 f…

ToolsSet之:渐变色生成工具

ToolsSet是微软商店中的一款包含数十种实用工具数百种细分功能的工具集合应用&#xff0c;应用基本功能介绍可以查看以下文章&#xff1a; Windows应用ToolsSet介绍https://blog.csdn.net/BinField/article/details/145898264 ToolsSet中Media菜单下的Gradient Color工具是一…

智能守护电网安全:探秘输电线路测温装置的科技力量

在现代电力网络的庞大版图中&#xff0c;输电线路如同一条条 “电力血管”&#xff0c;日夜不息地输送着能量。然而&#xff0c;随着电网负荷不断增加&#xff0c;长期暴露在户外的线路&#xff0c;其线夹与导线在电流热效应影响下&#xff0c;极易出现温度异常。每年因线路过热…

云服务器如何自动更新系统并保持安全?

云服务器自动更新系统是保障安全、修补漏洞的重要措施。下面是常见 Linux 系统&#xff08;如 Ubuntu、Debian、CentOS&#xff09;和 Windows 服务器自动更新的做法和建议&#xff1a; 1. Linux 云服务器自动更新及安全维护 Ubuntu / Debian 系统 手动更新命令 sudo apt up…

Spring Advisor增强规则实现原理介绍

Spring Advisor增强规则实现原理介绍 一、什么是 Advisor&#xff1f;1. Advisor 的定义与本质接口定义&#xff1a; 2. Advisor 的核心作用统一封装切点与通知构建拦截器链的基础实现增强逻辑的灵活组合 二. Sprin当中的实现逻辑1 Advisor 接口定义2 PointcutAdvisor 接口定义…

vscode实时预览编辑markdown

vscode实时预览编辑markdown 点击vsode界面&#xff0c;实现快捷键如下&#xff1a; 按下快捷键 CtrlShiftV&#xff08;Windows/Linux&#xff09;或 CommandShiftV&#xff08;Mac&#xff09;即可在侧边栏打开 Markdown 预览。 效果如下&#xff1a;