Spring 初識
CyrusHuang發表於2024-06-29
spring 核心思想
- IOC/DI:一個意思,IOC 是思想,DI 是實現
- AOP:面向切面程式設計,OOP 是物件導向面呈
IOC 容器
- 底層依靠 BeanFactory 實現,內部有個 beanFactory 屬性
- beanFactory.singletonObjects 屬性,是一個 map,這個就是單例池,所有的完整的 bean 放在這裡
- beanFactory.beanDefinitionMap 屬性,也是一個 map,放的是所有的的 bean 定義物件(xml定義bean的資訊,id,class,lazy,scope 等)
- beanFactory.factoryBeanObjectCache 屬性,也是一個 map,放的是由 FactoryBean 方式建立的 bean
- 建立bean的方式是多樣的,如果是 FactoryBean 方式,真實 bean 放在 factoryBeanObjectCache,此時 singletonObjects 放的是工廠物件
- 如果建立方式不是 FactoryBean,bean 就放在 singletonObjects 中
AOP
- 根本作用是增強 bean,生成 bean 的代理物件,後面呼叫的時候也是使用這個代理物件,從而達到擴充套件 bean 的目的,比如事物、日誌
- 底層根據代理實現,可選的有 JDK 動態代理和 cglib
- 如果有介面,就使用 jdk 動態代理,也是 spring 預設的方式
- 如果沒有介面,就只能使用 cglib 來建立,此時必須保證類沒有被 final 修飾,因為建立的代理物件是類的子類的物件
- AOP 也是一種思想,實現方式有 AspectJ 和 Advisor
- AspectJ 更強大更靈活 Advisor 功能更單一但是更方便
- spring 事物管理就是使用 Advisor 實現的,因為事物的功能就比較單一:開啟事物、提交事物、回滾事物
- 如果自己要做 AOP 一般都是使用 AspectJ
DI
- 方式是多樣的,可以構造注入、setter 注入、屬性注入(屬性注入最方便最主流,這裡只說屬性注入)
- @Value 注入基本型別,字串、布林值、整形、BigDecimal 等,也可以使用 SpEL 表示式讀取 properties 和 yaml 配置
- @Autowired 和 @Resource 注入 bean
- @Autowired 是 spring 的註解,@Resource 是 java 的(spring 也提供瞭解析方法,所以也能用)
- @Autowired 先根據型別注入,如果發現多個再根據名稱匹配。@Resource 相反,@Resource 先根據名稱注入,如果找不到再根據型別注入
- @Autowired 如果有多個會報錯,可以配合 @Qualifier(name = xxx) 指定名稱,如果根據名稱還是有多個依然會報錯
- bean 可以使用使用 @Primary 修飾,提高優先順序,@Autowired 如果有多個就不會報錯了,優先使用這個 bean
- @Resource 可以指定名稱 @Resource(name = xxx)
- @Autowired 和 @Resource 根據名稱匹配 bean 時如果不指定 name 屬性,都是屬性名而不是類首字母小寫
迴圈依賴
- 三種場景會產生
- bean 內部引入自己
- 兩個 bean 互相依賴
- 多個 bean 互相依賴
- 解決方案是三級快取
- 一級快取:singletonObjects 最終放 bean 的單例池
- 二級快取:earlySingletonObjects 半成本的 bean,已經有被引用了
- 三級快取:singletonFactories 半成品的 bean,還未被引用,物件剛被建立就丟這裡
- 三級快取工作原理,需要知道 bean 生命週期才能理解,在後面的文章中再詳細說
擴充套件點(這裡只列出能擴充套件的方式,後面文章再說怎麼具體擴充套件)
- BeanFactoryPostProcessor
- 各種 aware 回撥介面
- beanPostProcessor
- InitializingBean
- 自定義 init 方法