Spring 系列(一):用三条主线理解 Spring:BeanDefinition、生命周期与 AOP

用三条主线理解 Spring:BeanDefinition、生命周期与 AOP

如果只能用三条主线来理解 Spring 框架,那么一定是:

BeanDefinition 的加载、Bean 的生命周期、AOP 如何嵌入生命周期。

Spring 中绝大多数看起来"复杂"的机制,本质上都是这三点的组合与演化。


一、为什么要用"三条主线"来理解 Spring?

在学习 Spring 的过程中,很多人都会遇到类似困惑:

  • 注解越来越多,却不知道它们到底在什么时候生效
  • 自动装配看似神秘,不清楚真正的触发点
  • 事务、AOP、循环依赖的问题反复出现

根本原因并不是 Spring 太复杂,而是没有从结构性视角去理解它

Spring 并不是一个"以注解为中心"的框架,而是一个分阶段、强约束的 IoC 容器系统。从整体上看,它几乎所有能力都围绕三个阶段展开:

  1. 容器结构的构建阶段(BeanDefinition)
  2. 对象创建与管理阶段(Bean 生命周期)
  3. 方法行为增强阶段(AOP)

抓住这三条主线,绝大多数 Spring 行为都可以被反向推导出来。


二、第一条主线:BeanDefinition ------ 容器结构层

1. Spring 真正管理的不是 Bean,而是 BeanDefinition

在 Spring 容器启动的早期,并不会立刻创建任何业务对象。此时 Spring 关注的核心问题只有一个:

容器里应该有哪些 Bean,它们应该如何被创建?

这些信息不会以"对象"的形式存在,而是被统一抽象为:

text 复制代码
BeanDefinition

你可以把 BeanDefinition 理解为一张"造 Bean 的说明书",其中包含:

  • Bean 对应的 class
  • scope(singleton / prototype)
  • 是否懒加载
  • 依赖关系
  • 工厂方法
  • 初始化 / 销毁方法

在这个阶段,容器中只有定义,没有实例。


2. BeanDefinition 阶段能做什么?

这是 Spring 启动过程中唯一可以改变容器结构的阶段

在这一阶段,框架或用户代码可以:

  • 新增 BeanDefinition
  • 删除或替换已有 BeanDefinition
  • 决定 Bean 是否注册
  • 修改 scope、role、lazy 等元信息

一旦进入 Bean 生命周期阶段,容器会冻结配置,结构将不再允许被修改。


3. 为什么大量框架注解都工作在这一阶段?

因为只有在 BeanDefinition 阶段,注解才能真正影响"有没有这个 Bean"。

常见例子包括:

  • MyBatis 的 @Mapper
  • Dubbo 的 @EnableDubbo
  • Spring Boot 的自动装配

这些注解背后,通常都会借助:

  • ImportSelector
  • ImportBeanDefinitionRegistrar
  • BeanDefinitionRegistryPostProcessor

它们的目标只有一个:

把注解携带的元信息,转换成 BeanDefinition 并注册进容器。


三、第二条主线:Bean 生命周期 ------ 对象管理层

当所有 BeanDefinition 注册完成并被冻结之后,Spring 才真正进入"创建对象"的阶段。

1. 生命周期的本质是什么?

从本质上看,Bean 生命周期做的事情只有一件:

把一次简单的 new 操作,拆分成多个可插拔的阶段。

一个典型的单例 Bean,会经历如下步骤:

  1. 实例化(构造方法执行)
  2. 属性填充(依赖注入)
  3. Aware 接口回调
  4. 初始化前处理(BeanPostProcessor
  5. 初始化方法(@PostConstruct / afterPropertiesSet / init-method)
  6. 初始化后处理(BeanPostProcessor
  7. 放入单例池

这种拆分,为 Spring 的扩展能力奠定了基础。


2. 生命周期为什么要拆得这么细?

因为 Spring 需要在对象创建的不同时间点,允许"外部逻辑"介入,例如:

  • 依赖注入
  • 循环依赖处理
  • AOP 代理生成
  • 容器感知能力(Aware)

如果对象一开始就被完整创建,这些能力将无法实现。


3. 循环依赖为什么只能 setter 注入解决?

Spring 解决循环依赖的前提条件是:

对象已经被实例化出来,即使它还没有完成初始化。

Setter / Field 注入的流程是:

text 复制代码
实例化对象
  ↓
提前暴露对象引用
  ↓
依赖注入

而构造器注入在实例化阶段就需要完整依赖:

text 复制代码
构造器执行
  ↓
需要依赖对象

此时对象尚不存在,Spring 无法提前暴露引用,因此无法解决构造器循环依赖。


四、第三条主线:AOP ------ 行为增强层

AOP 并不是一个独立于 IoC 的系统,而是深度嵌入 Bean 生命周期中的一种扩展机制

1. AOP 真正发生在什么时候?

AOP 并不是在方法调用时"临时判断要不要增强",而是在 Bean 创建完成之后,就已经决定好要不要生成代理对象

也就是说:

AOP 发生在 Bean 创建期,行为生效在方法调用期。


2. AOP 是如何嵌入生命周期的?

Spring AOP 通过实现 BeanPostProcessor,在 初始化后阶段 对 Bean 进行处理。

以事务为例:

  • @Transactional 只是一个元数据注解
  • 真正起作用的是 TransactionInterceptor
  • 它会在 postProcessAfterInitialization 阶段判断是否需要创建代理

如果需要,Spring 会返回代理对象,并用它替换原始 Bean。


3. 为什么事务、自调用会失效?

java 复制代码
@Service
public class AService {
    @Transactional
    public void a() {
        this.b();
    }

    @Transactional
    public void b() {}
}

实际调用路径是:

text 复制代码
外部调用 → 代理对象.a()
            → 目标对象.a()
                → this.b()

this.b() 并没有经过代理,自然也不会进入事务拦截器,因此事务不会生效。


4. AOP 与 BeanDefinition 的边界

AOP 只能:

  • 包装 Bean
  • 拦截方法调用

但它不能

  • 决定 Bean 是否存在
  • 改变 Bean 的 scope
  • 修改依赖结构

这些能力,全部属于 BeanDefinition 阶段


五、用这三条主线反推 Spring 的一切行为

掌握这三条主线之后,很多问题都可以自然解释:

  • 注解不生效 → BeanDefinition 是否被注册
  • 循环依赖异常 → 是否构造器注入
  • 事务不生效 → 是否走了代理
  • Starter 无感接入 → BeanDefinition 阶段完成装配

六、一句话总结

Spring 的核心可以归纳为三件事:

第一,构建容器结构(BeanDefinition);
第二,按生命周期管理对象(Bean Lifecycle);
第三,在生命周期合适的阶段织入 AOP 行为增强。

当你从这个视角再回头看 Spring,会发现:

  • 它并不神秘
  • 也不全是"魔法"
  • 而是一个被工程需求不断扩展、但主干极其清晰的框架

理解这三条主线,你就已经站在了 Spring 框架设计者的视角

相关推荐
云烟成雨TD20 小时前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
Java成神之路-21 小时前
SpringMVC 响应实战指南:页面、文本、JSON 返回全流程(Spring系列13)
java·spring·json
砍材农夫21 小时前
spring-ai 第六模型介绍-聊天模型
java·人工智能·spring
云烟成雨TD1 天前
Spring AI Alibaba 1.x 系列【5】ReactAgent 构建器深度源码解析
java·人工智能·spring
Flittly1 天前
【SpringAIAlibaba新手村系列】(15)MCP Client 调用本地服务
java·笔记·spring·ai·springboot
Flittly1 天前
【SpringAIAlibaba新手村系列】(14)MCP 本地服务与工具集成
java·spring boot·笔记·spring·ai
mfxcyh1 天前
基于xml、注解、JavaConfig实现spring的ioc
xml·java·spring
Flittly1 天前
【SpringAIAlibaba新手村系列】(13)Tool Calling 函数工具调用技术
java·spring boot·spring·ai
xdscode1 天前
Spring 依赖注入方式全景解析
java·后端·spring