Spring BeanDefinition 与 Bean 生命周期、循环依赖解析
一、BeanDefinitionBean 定义的元数据载体BeanDefinition 是 Spring 对 Bean 信息的抽象描述包含了创建 Bean 所需的全部元数据如类名、作用域、依赖关系、生命周期回调方法等。Spring 容器通过解析配置注解、XML、Java 配置生成 BeanDefinition再基于 BeanDefinition 实例化和初始化 Bean。其核心底层结构基于AbstractBeanDefinition关键属性及源码逻辑如下1.1 核心属性scope作用域scope 定义了 Bean 的创建方式和生命周期范围决定了 Bean 实例的复用规则默认值为singleton单例。singleton单例默认 特性容器启动时非懒加载模式下创建 Bean 实例容器销毁时销毁实例整个容器内该 Bean 实例全局唯一核心源码AbstractBeanFactory.doGetBean()中判断 scope 为 singleton 时优先从缓存一级缓存获取实例若缓存不存在则调用createBean()创建创建后存入缓存复用。prototype原型特性每次通过getBean()获取 Bean 时都会创建新的实例Spring 容器仅负责实例化不管理实例的销毁销毁由用户自行处理核心源码AbstractBeanFactory.doGetBean()中判断 scope 为 prototype 时直接调用createBean()创建新实例不存入缓存。request请求作用域Web 环境 特性绑定 HTTP 请求生命周期每个请求创建一个新实例请求结束后实例销毁。session会话作用域Web 环境 特性绑定 HTTP 会话生命周期每个会话创建一个新实例会话失效后实例销毁。1.2 核心属性lazyInit懒加载lazyInit 控制单例 Bean 的创建时机仅对 singleton 作用域有效prototype 默认为“懒加载”每次获取都新建。true懒加载 特性无论容器是否启动仅在首次通过getBean()获取 Bean 时才创建实例核心源码DefaultListableBeanFactory.preInstantiateSingletons()方法中会跳过标记为懒加载的 Bean不进行容器启动时的预初始化。false非懒加载默认 特性容器启动过程中在refresh()方法的finishBeanFactoryInitialization()阶段完成所有单例 Bean 的预初始化。1.3 核心属性autowireMode自动装配模式autowireMode 定义了 Bean 依赖的自动注入规则决定了 Spring 如何查找并注入依赖的 Bean默认值为AUTOWIRE_NO不自动装配。AUTOWIRE_NO0默认不自动装配仅支持手动注入如Autowired、Resource注解或 XML 中显式配置。AUTOWIRE_BY_TYPE1按类型装配根据依赖的 Bean 类型Class从容器中查找匹配的 Bean若存在多个同类型 Bean 则抛出异常。AUTOWIRE_BY_NAME2按名称装配根据依赖的字段名或 setter 方法参数名匹配容器中同名的 BeanBean 名称默认为首字母小写的类名。AUTOWIRE_CONSTRUCTOR3按构造器装配根据构造方法的参数类型从容器中查找匹配的 Bean注入到构造方法中完成实例化。核心源码自动装配逻辑在AbstractAutowireCapableBeanFactory.populateBean()方法中执行该方法会根据 autowireMode 的配置完成 Bean 的属性注入。二、Bean 的完整生命周期Bean 的生命周期是从“基于 BeanDefinition 创建实例”到“容器销毁实例”的全流程核心分为 5 个阶段实例化 → 属性复制依赖注入 → 初始化 → 使用 → 销毁。每个阶段都有对应的扩展点如接口回调、自定义方法供开发者介入。2.1 阶段 1实例化Instantiation核心目标创建 Bean 的实例对象内存中分配空间此时尚未进行属性注入。实现方式构造函数实例化Spring 容器通过 BeanDefinition 中的类名调用默认构造函数或带参构造函数创建实例最常用方式工厂方法实例化通过配置的工厂类和工厂方法创建实例如 XML 中配置factory-bean和factory-method。2.2 阶段 2属性复制Populate Bean核心目标为实例化后的 Bean 注入依赖的属性值即依赖注入。实现方式setter 方法注入通过 Bean 的 setter 方法注入属性值配合 AUTOWIRE_BY_TYPE 或 AUTOWIRE_BY_NAME 自动装配或手动配置字段注入通过 Java 反射机制直接为 Bean 的字段赋值如Autowired字段注入无需 setter 方法构造器注入在实例化阶段通过带参构造函数注入依赖配合 AUTOWIRE_CONSTRUCTOR 自动装配。2.3 阶段 3初始化Initialization核心目标属性注入完成后执行额外的初始化操作如初始化资源、校验属性确保 Bean 处于可用状态。扩展方式执行顺序接口回调 → 自定义方法实现InitializingBean接口重写afterPropertiesSet()方法Spring 会在属性注入后自动调用自定义初始化方法通过PostConstruct注解标记方法或在 BeanDefinition 中配置init-methodXML 或Bean(initMethod xxx)Spring 会自动调用该方法。2.4 阶段 4使用In Use核心目标Bean 初始化完成后可通过 Spring 容器的getBean()方法获取实例调用其方法执行业务逻辑。此时 Bean 处于完全可用状态。2.5 阶段 5销毁Destruction核心目标容器关闭或手动销毁 Bean 时执行资源释放等清理操作如关闭连接池、释放文件资源。扩展方式执行顺序接口回调 → 自定义方法实现DisposableBean接口重写destroy()方法Spring 会在容器关闭时自动调用自定义销毁方法通过PreDestroy注解标记方法或在 BeanDefinition 中配置destroy-methodXML 或Bean(destroyMethod xxx)Spring 会自动调用该方法。三、循环依赖与三级缓存解决方案循环依赖是指两个或多个 Bean 互相依赖如 A 依赖 BB 依赖 A。Spring 通过“三级缓存”机制解决单例 Bean 的 setter 注入循环依赖而原型 Bean、构造器注入的循环依赖无法解决。3.1 三级缓存的核心定义Spring 容器通过三个缓存Map 结构存储不同状态的单例 Bean协同解决循环依赖一级缓存singletonObjects存储“完全初始化完成”的单例 Bean 实例实例化、属性注入、初始化均完成供全局复用二级缓存earlySingletonObjects存储“实例化完成但未初始化”的单例 Bean 实例仅完成第一步实例化属性注入和初始化未完成三级缓存singletonFactories存储“单例 Bean 工厂”ObjectFactory用于延迟生成“实例化完成但未初始化”的 Bean 实例早期引用。3.2 三级缓存解决循环依赖的流程以 A、B 单例 setter 注入为例Spring 容器启动时初始化 A Bean调用createBean()完成 A 的实例化未注入属性、未初始化然后将 A 的单例工厂singletonFactory存入三级缓存为 A 注入依赖 BSpring 从容器中查找 B发现 B 未创建开始初始化 B初始化 B Bean调用createBean()完成 B 的实例化将 B 的单例工厂存入三级缓存为 B 注入依赖 ASpring 依次查询一级、二级缓存均未找到完全初始化的 A然后查询三级缓存通过 A 的单例工厂获取 A 的早期引用实例化完成但未初始化将 A 的早期引用从三级缓存移除存入二级缓存然后将 A 的早期引用注入到 B 中B 完成属性注入后执行初始化操作初始化完成后存入一级缓存此时 B 中的 A 仍为早期引用但不影响 B 的初始化回到 A 的属性注入流程从一级缓存中找到已完全初始化的 B将 B 注入到 A 中A 完成属性注入后执行初始化操作初始化完成后存入一级缓存覆盖之前的早期引用循环依赖解决A、B 均完成初始化可正常使用。3.3 无法解决的循环依赖场景原型 Bean 循环依赖原型 Bean 每次获取都新建实例不存入三级缓存因此无法通过缓存传递早期引用会抛出BeanCurrentlyInCreationException异常构造器注入循环依赖构造器注入在实例化阶段就需要依赖对象而此时依赖对象尚未实例化无法生成早期引用因此无法解决会抛出BeanCurrentlyInCreationException异常。