深入理解Spring循环依赖解决机制

0 下载量 186 浏览量 更新于2024-09-01 收藏 86KB PDF 举报
"简单了解Spring循环依赖解决过程" 在Spring框架中,循环依赖指的是两个或多个bean之间形成相互依赖的关系,导致它们无法正常初始化。Spring提供了几种机制来处理这种问题,主要集中在属性的循环依赖上,因为构造器的循环依赖在Java中通常是无法解决的,会导致`StackOverflowError`。下面我们将深入探讨Spring如何解决属性循环依赖。 1. **单例bean的三级缓存** Spring使用三级缓存来处理单例bean的循环依赖问题。这三级缓存分别是: - `SingletonObjects`: 存储完全初始化好的bean,也就是已经完成了依赖注入的对象。 - `EarlySingletonObjects`: 存储的是早期暴露的bean,此时bean只是实例化了,但还没有完成依赖注入。 - `SingletonFactories`: 存储bean的工厂,可以用来创建bean实例。 2. **实例化过程** 当Spring遇到一个bean的实例化请求时,会按照以下步骤进行: - **预实例化**: 对于单例bean,Spring会在容器启动时进行预实例化,这样可以尽早发现循环依赖。 - **创建Bean实例**: 使用`DefaultListableBeanFactory`的`createBean()`方法开始实例化过程。 - **填充属性值**: - **检查早起暴露**: 如果bean已经存在于`EarlySingletonObjects`中,那么它会被直接返回,从而打破循环依赖。 - **如果没有早起暴露**: Spring会创建一个代理,将这个未初始化的bean放入`SingletonFactories`缓存,然后尝试继续实例化其他依赖。 - **依赖注入**: 此时如果遇到了循环依赖,Spring会从`SingletonFactories`中取出对应的bean工厂,使用工厂创建一个代理对象,将这个代理对象注入到依赖者中,从而避免了直接依赖未初始化的bean。 3. **依赖注入阶段** - **填充属性**: 在依赖注入过程中,Spring使用了` Aware`接口(如`BeanFactoryAware`、`ApplicationContextAware`等)让bean可以感知到容器,从而在必要时获取其他bean。 - **属性注入**: 通过`PropertyPlaceholderConfigurer`、`AutowiredAnnotationBeanPostProcessor`等后处理器完成属性的自动装配。 - **最终初始化**: 所有依赖注入完成后,bean才会被添加到`SingletonObjects`缓存中,成为完全初始化的bean。 4. **原型bean与循环依赖** 对于原型(prototype)作用域的bean,Spring不会尝试解决循环依赖,因为原型bean每次请求都会创建一个新的实例,这样的场景下循环依赖通常不是问题。 5. **注意事项** - Spring的循环依赖解决方案只适用于单例bean,对于 prototype 或其他作用域的bean,开发者需要自行处理循环依赖问题。 - Spring不支持在构造器中的循环依赖,因为它无法在构造阶段预测和解决依赖关系。 - Spring的循环依赖解决方案依赖于AOP代理,因此如果关闭了AOP,循环依赖可能无法正确处理。 Spring通过其独特的三级缓存机制,以及在bean生命周期的不同阶段进行干预,有效地解决了单例bean的循环依赖问题。然而,设计时应尽量避免循环依赖,以提高代码的可读性和可维护性。