Spring 容器在建立單例 Bean 時,遵循「不等 Bean 完全初始化完成,就將建立 Bean 的 ObjectFactory 提早放入緩存」的原則。這項機制是解決循環依賴的關鍵基石。
Spring 使用三個 Map 協同管理單例 Bean 的不同生命週期狀態:
ObjectFactory,可延遲生成早期 Bean 參考。singletonObjects.get(beanName) // 1. 嘗試從成品緩存獲取
↓ null
earlySingletonObjects.get(beanName) // 2. 嘗試從早期緩存獲取(循環依賴場景)
↓ null
singletonFactories.get(beanName) // 3. 從工廠緩存獲取 ObjectFactory
↓ getObject()
earlySingletonObjects.put(beanName, obj) // 4. 將生成的早期實例放入早期緩存
singletonFactories.remove(beanName) // 5. 移除工廠,避免重複生成
實作 FactoryBean<T> 介面的類別,其 getObject() 回傳值才是真正被容器管理的 Bean。獲取方式:
ctx.getBean("book") → 取得 FactoryBean#getObject() 產出的物件。ctx.getBean("&book") → 取得 FactoryBean 本身。@Autowired、XML <property> 等。BeanNameAware、BeanFactoryAware、ApplicationContextAware 等。postProcessBeforeInitialization。InitializingBean#afterPropertiesSet()、@PostConstruct、XML init-method。postProcessAfterInitialization(AOP 代理在此生成)。DisposableBean、@PreDestroy、XML destroy-method。假設 A 依賴 B,B 依賴 A:
ObjectFactory 至 singletonFactories。ObjectFactory。singletonFactories 取得 A 的早期參考 → 完成 B 初始化 → 放入 singletonObjects。singletonObjects。若關閉「允許循環依賴」(allowCircularReferences=false),步驟 4 將拋出 BeanCurrentlyInCreationException。