注:碼友們,我們是從設計的角度一步步學習和分解Spring;所以不要一上來就想看源碼,也不需要關心Spring具體加載進去的;我們只封裝工具(如IoC),至于調用,暫時不用考慮;(是所謂:抓魯迅關我周樹人什么事)
一、設計理念
此處碼友們可以先思考以下,如果僅針對IoC這個點來說,你會如何設計,“動手之前先思考”,所以我想機智的碼友會有以下思考:
1、現在將bean的控制權交給框架了,碼友不用自己new了,那么肯定要有一個創建bean對象的工具,以及存放創建好的bean的容器;
2、針對創建的對象的工具,從設計角度,首先得支持多種方式吧(比如:XML/注解/Java Config),要不然太局限沒人用可還得了;
3、創建好的對象存放的方式,最容易想到的應該是Map,以鍵值對形式存儲;
4、聰明的碼友,又會想到既然bean是框架生成和存儲的,那么此處會存在一個問題,bean是一下子就能創建好的嗎?比如A依賴了B,B依賴了C,那么先創建A的時候,B還沒創建,那是不是B就無法完全創建了,B、C同理;那么針對這個問題,肯定要有一個方案去解決,此處假設有個“黑盒”,已經解決了,本篇不論。
5、聰明的碼友,思路是不是已經掌握了,萬變不離其宗,這個思路握在手里,再細看以下內容。
6、面向對象的核心特性不要忘了:封裝、繼承、多態
7、23種設計模式、七大軟件設計原則也需要作為基礎知識,從而去理解和“設計”Spring
1. 控制反轉(Inversion of Control, IoC)
-
核心思想:將對象的創建與依賴管理權從應用程序代碼轉移到框架或容器中。
-
實現目標:
- 解耦組件間的依賴關系,降低代碼耦合度。
- 提供統一的配置管理(XML/注解/Java Config),簡化對象生命周期管理。
- 支持靈活的擴展性(通過接口、回調、擴展點)。
2. 依賴注入(Dependency Injection, DI)
- 定義:由容器動態注入依賴對象,而非硬編碼依賴關系。
- 實現方式:
- 構造器注入(Constructor Injection)。
- Setter 方法注入(Setter Injection)。
- 字段注入(Field Injection,基于注解)。
3. 松耦合與可擴展性
-
松耦合:通過接口抽象與依賴注入,使組件之間無需直接引用具體實現。
-
可擴展性:
- 支持自定義 BeanPostProcessor、BeanFactoryPostProcessor。
- 允許通過 SPI(Service Provider Interface)機制擴展容器功能。
4. 配置元數據
-
支持形式:
- XML 配置(
<bean>
標簽)。 - 注解配置(
@Component
、@Autowired
、@Configuration
)。 - Java 配置類(
@Bean
注解)。
- XML 配置(
-
統一抽象:
BeanDefinition
是所有配置的抽象表示,支持多種配置源的解析與注冊。
二、核心組件與職責劃分
結合設計理念,做組件拆分和定義,這里羅列的是不斷迭代后結果,而我們如果從頭設計,就只需要重點考慮核心: IoC 容器、Bean 的元數據、配置源
組件名稱 | 職責 |
---|---|
BeanFactory | 最基礎的 IoC 容器,提供延遲加載(懶加載)Bean 的能力。 |
ApplicationContext | 擴展自 BeanFactory,增加企業級功能(事件發布、國際化、資源加載等)。 |
BeanDefinition | 描述 Bean 的元數據(類名、作用域、依賴關系、初始化/銷毀方法等)。 |
BeanDefinitionReader | 解析配置源(XML、注解、Java Config)并生成 BeanDefinition 。 |
BeanFactoryPostProcessor | 在容器加載 BeanDefinition 之前修改配置元數據。 |
BeanPostProcessor | 在 Bean 實例化前后進行攔截處理(如 AOP 代理、屬性增強)。 |
三、關鍵設計模式
你已經是一個成熟的碼農了,應該學會套公式了
1. 工廠模式(Factory Pattern)
- 應用場景:
BeanFactory
作為工廠接口,負責創建和管理 Bean 實例。 - 實現類:
DefaultListableBeanFactory
、XmlBeanFactory
。 - 優勢:解耦對象創建邏輯與使用邏輯,支持靈活的實例化策略(反射、工廠方法)。
2. 單例模式(Singleton Pattern)
- 應用場景:默認情況下,Spring 容器中的 Bean 為單例作用域(
@Scope("singleton")
)。 - 實現機制:通過
DefaultSingletonBeanRegistry
維護單例池(Map<String, Object>
)。 - 擴展性:支持原型作用域(
@Scope("prototype")
)及自定義作用域。
3. 代理模式(Proxy Pattern)
-
應用場景:AOP 的實現(動態代理)。
-
實現方式:
- JDK 動態代理:基于接口生成代理類(適用于有接口的目標對象)。
- CGLIB 字節碼增強:直接修改字節碼生成子類代理(適用于無接口的目標對象)。
-
關鍵類:
ProxyFactory
、JdkDynamicAopProxy
、CglibAopProxy
。
4. 觀察者模式(Observer Pattern)
-
應用場景:事件驅動模型(
ApplicationEvent
與ApplicationListener
)。 -
實現機制:
- 事件發布:
ApplicationContext.publishEvent(event)
。 - 事件監聽:通過
@EventListener
注解或ApplicationListener
接口注冊監聽器。
- 事件發布:
5. 模板方法模式(Template Method Pattern)
- 應用場景:
BeanFactory
的初始化流程(refresh()
方法)。 - 實現步驟:
public void refresh() {this.prepareRefresh();registerBeanDefinitions(); // 注冊 BeanDefinitionprepareBeanFactory(); // 配置容器postProcessBeanFactory(); // 擴展點instantiateSingletons(); // 實例化單例 Bean
}
四、源碼解析
此處就核心邏輯簡要說明,后續章節中我們會針對以下章節分別做詳細源碼解析說明
1. IoC 容器啟動流程
-
入口:
ApplicationContext
的refresh()
方法。 -
關鍵步驟:
- 加載配置:解析 XML/注解/Java Config,生成
BeanDefinition
。 - 注冊 BeanDefinition:將
BeanDefinition
存入BeanDefinitionRegistry
。 - 實例化單例 Bean:通過
DefaultListableBeanFactory
的preInstantiateSingletons()
方法。 - 依賴注入:通過
AutowiredAnnotationBeanPostProcessor
注入依賴。
- 加載配置:解析 XML/注解/Java Config,生成
2. Bean 生命周期管理
-
流程圖:
[BeanDefinition 加載] → [Bean 實例化] → [屬性注入] → [初始化方法] → [使用 Bean] → [銷毀方法]
-
關鍵類:
AbstractAutowireCapableBeanFactory
:負責實例化與屬性注入。InitializingBean
:定義afterPropertiesSet()
初始化方法。DisposableBean
:定義destroy()
銷毀方法。
3. 依賴注入實現
-
字段注入:
- 通過
AutowiredAnnotationBeanPostProcessor
處理@Autowired
注解。 - 使用
AutowiredFieldElement.inject()
方法完成字段賦值。
- 通過
-
構造器注入:
- 通過
ConstructorResolver.autowireConstructor()
解析構造器參數。
- 通過
4. AOP 與動態代理
-
代理創建:
-
判斷目標對象是否為接口:
- 是 → 使用
JdkDynamicAopProxy
。 - 否 → 使用
CglibAopProxy
。
- 是 → 使用
-
-
切面織入:
- 通過
Advisor
定義切面邏輯(Pointcut
+Advice
)。 - 在代理對象的方法調用中插入
invoke()
邏輯(如@Before
、@Around
)。
- 通過
五、高級特性與擴展
1. Bean 作用域
- 單例(Singleton):默認作用域,整個容器共享一個實例。
- 原型(Prototype):每次請求創建新實例。
- Web 作用域:
request
、session
(需 Web 環境支持)。 - 自定義作用域:通過
Scope
接口實現(如ThreadScope
)。
2. 條件化配置
@Conditional
注解:根據條件決定是否注冊 Bean。@Profile
注解:按環境激活不同配置(如開發、測試、生產)。
3. 擴展點機制
BeanFactoryPostProcessor
:修改BeanDefinition
(如PropertyPlaceholderConfigurer
)。BeanPostProcessor
:攔截 Bean 實例化過程(如AOPProxy
創建)。
4. 性能優化
- 懶加載(Lazy Initialization):通過
@Lazy
延遲加載 Bean。 - 緩存單例池:
DefaultSingletonBeanRegistry
使用ConcurrentHashMap
提高并發性能。
六、應用場景與示例
1. 基于 XML 的配置
<beans><bean id="userService" class="com.albert.UserService"><property name="userDao" ref="userDao"/></bean><bean id="userDao" class="com.albert.UserDaoImpl"/>
</beans>
2. 基于注解的配置
@Service
public class UserService {@Autowiredprivate UserDao userDao;
}
3. 基于 Java Config 的配置
@Configuration
public class AppConfig {@Beanpublic UserService userService() {return new UserService(userDao());}@Beanpublic UserDao userDao() {return new UserDaoImpl();}
}
七、總結與展望
-
核心價值:
- 通過控制反轉與依賴注入,Spring IoC 實現了組件的解耦與復用,顯著提升了開發效率與代碼可維護性。
-
未來方向:
- 云原生支持:進一步優化容器啟動速度與資源占用(如 GraalVM 原生鏡像)。
- 無配置化:通過代碼生成(如 Lombok)或元編程減少顯式配置。
- 服務治理集成:與微服務框架(如 Spring Cloud)深度整合,實現分布式場景下的依賴管理。