Spring 框架的設計理念與設計模式
Spring 框架的設計理念與設計模式
Spring核心學習點
- IoC容器:Spring核心是IoC容器,所以一定要透徹理解什麼是IoC容器,以及如何配置及使用容器,其他所有技術都是基於容器實現的;
- 面向切面程式設計:首先還是明確概念,基本配置,最後是實現原理,接下來就是資料庫事務管理,其實Spring管理事務是通過面向切面程式設計實現的
一、Spring核心容器元件
Spring 的三大元件 :Bean 、 Context、Core
Bean(一場演出中的演員):
提供了框架的基礎部分,包括反轉控制和依賴注入。其中Bean Factory是容器核心,本質是“工廠設計模式”的實現,而且無需程式設計實現“單例設計模式”,單例完全由容器控制,而且提倡面向介面程式設計,而非面向實現程式設計;所有應用程式物件及物件間關係由框架管理,從而真正把你從程式邏輯中把維護物件之間的依賴關係提取出來,所有這些依賴關係都由BeanFactory來維護
Context(演出的舞臺背景):
以Core和Beans為基礎,整合Beans模組功能並新增資源繫結、資料驗證、國際化、Java EE支援、容器生命週期、事件傳播等;核心介面是ApplicationContext,
ApplicationContext將完成:
- (1)標識一個應用環境
- (2)利用BeanFactory建立Bean物件
- (3)儲存物件關係表
- (4)能夠捕獲各種事件
Core(演出的道具):
封裝了框架依賴的最底層部分,包括資源訪問、型別轉換及一些常用工具類
二、Spring核心理念:
- 面向Bean程式設計:將物件間的依賴關係用配置檔案管理,在一個叫做IOC容器中管理,這個容器裡就是被Bean包裹的物件
IoC容器工作原理
IoC容器實際上是Context元件結合另外其他兩個元件共同構建了一個Bean的關係網。
(1)初始化
初始化的過程主要就是讀取XML資源,並解析,最終註冊到Bean Factory中
初始化的流程:
!init
然後會重新整理,將該新加入的Bean放入整個關係網中去:重新整理的入口就在AbstractApplicationContext
的refresh
方法裡:
public void refresh() throws BeansException, IllegalStateException { Object var1 = this.startupShutdownMonitor; synchronized(this.startupShutdownMonitor) { //為重新整理準備新的Context this.prepareRefresh(); //重新整理所有BeanFactory子容器 ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); //建立BeanFactory this.prepareBeanFactory(beanFactory); //新增一些工具類 try { // this.postProcessBeanFactory(beanFactory); // this.invokeBeanFactoryPostProcessors(beanFactory); // this.registerBeanPostProcessors(beanFactory); this.initMessageSource(); this.initApplicationEventMulticaster(); this.onRefresh(); this.registerListeners(); this.finishBeanFactoryInitialization(beanFactory); this.finishRefresh(); } catch (BeansException var9) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } }
這個方法就是構建IoC容器的整個流程,非常重要,主要包含著幾個步驟:
(1)構建BeanFactory,以便生產所需的“演員”
(2)註冊可能感興趣的事件
(3)建立Bean 例項物件
(4)觸發被監聽的事件
首先this.obtainFreshBeanFactory(); //建立BeanFactory
中會執行解析和註冊bean的過程,通過parseBeanDefinitionElement將XML的元素解析為BeanDefinition,然後存在BeanDefinitionHolder中,然後再利用BeanDefinitionHolder將BeanDefinition註冊,實質就是把BeanDefinition的例項put進BeanFactory中.
註冊過程中,最核心的一句就是:this.beanDefinitionMap.put(beanName, beanDefinition),也就是說註冊的實質就是以beanName為key,以beanDefinition為value,將其put到HashMap中。
其中,這三行程式碼對Spring 的功能擴充套件起到了關鍵作用:
this.postProcessBeanFactory(beanFactory); // -> 註冊實現了BeanPostProcessor介面的Bean
this.invokeBeanFactoryPostProcessors(beanFactory);// ->初始化和執行BeanFactoryPostProcessors beans
this.registerBeanPostProcessors(beanFactory); // -> 初始化和執行BeanPostProcessors beans
invokeBeanFactoryPostProcessors
方法主要是獲取實現BeanFactoryPostProcessors介面的子類,並且執行它的postProcessBeanFactory
方法.
這兩個介面的作用:
BeanFactoryPostProcessor和BeanPostProcessor,這兩個介面,都是Spring初始化bean時對外暴露的擴充套件點。
- BeanFactoryPostProcessor介面實現類可以在當前BeanFactory初始化後,bean例項化之前對BeanFactory做一些處理。BeanFactoryPostProcessor是針對於bean容器的,在呼叫它時,BeanFactory只加載了bean的定義,還沒有對它們進行例項化,所以我們可以通過對BeanFactory的處理來達到影響之後例項化bean的效果。
- BeanPostProcessor 介面定義了一個你可以自己實現的回撥方法,來實現你自己的例項化邏輯、依賴解決邏輯等,如果你想要在Spring完成物件例項化、配置、初始化之後實現自己的業務邏輯,你可以補充實現一個或多個BeanPostProcessor的實現。
如下圖所示:Spring Bean的生命週期:
!post
(2)依賴注入
當完成初始化IOC容器後,如果bean沒有設定lazy-init(延遲載入)屬性,那麼bean的例項就會在初始化IOC完成之後,及時地進行初始化。初始化時會先建立例項,然後根據配置利用反射對例項進行進一步操作,具體流程如下所示:
在AbstractAutowireCapableBeanFactory
類中,進行建立bean和注入bean的屬性
三、Spring中的設計模式
Spring 中的單例模式
Spring 中的代理模式
Spring中的 AOP就是給予動態代理實現的。
Spring 中的工廠模式
Spring中在各種BeanFactory以及ApplicationContext建立中都用到了典型的工廠方法模式,BeanFactory的設計原理如圖所示。
來看看其中BeanFactory原始碼:
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;
<T> T getBean(String var1, Class<T> var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
Object getBean(String var1, Object... var2) throws BeansException;
<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
boolean containsBean(String var1);
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
String[] getAliases(String var1);
}
Bean包裡主要包括Bean的定義、建立和解析,也就是配置xml檔案,被解析後就被轉化為Bean,由Spring統一管理.