Spring IOC 學習筆記
1、IoC思想 .
如何理解好Ioc呢?理解好Ioc的關鍵是要明確“誰控制誰,控制什麼,為何是反轉(有反轉就應該有正轉了),哪些方面反轉了”,那我們來深入分析一下:
●誰控制誰,控制什麼:傳統Java SE程式設計,我們直接在物件內部通過new進行建立物件,是程式主動去建立依賴物件;而IoC是有專門一個容器來建立這些物件,即由Ioc容器來控制物件的建立;誰控制誰?當然是IoC 容器控制了物件;控制什麼?那就是主要控制了外部資源獲取(不只是物件包括比如檔案等)。
●為何是反轉,哪些方面反轉了:有反轉就有正轉,傳統應用程式是由我們自己在物件中主動控制去直接獲取依賴物件,也就是正轉;而反轉則是由容器來幫忙建立及注入依賴物件;為何是反轉?因為由容器幫我們查詢及注入依賴物件,物件只是被動的接受依賴物件,所以是反轉;哪些方面反轉了?依賴物件的獲取被反轉了。
理解DI的關鍵是:“誰依賴誰,為什麼需要依賴,誰注入誰,注入了什麼”,那我們來深入分析一下:
●誰依賴於誰:當然是應用程式依賴於IoC容器;
●為什麼需要依賴:應用程式需要IoC容器來提供物件需要的外部資源;
●誰注入誰:很明顯是IoC容器注入應用程式某個物件,應用程式依賴的物件;
●注入了什麼:就是注入某個物件所需要的外部資源(包括物件、資源、常量資料)
2、Spring初始化IoC容器的過程。
Spring 先載入beanDefinition到beanFactory中(用map儲存,key是beanName),beanDefinition是bean資料結構的一種對映。然後處理beanDefiniton(怎麼處理?)。完成bean註冊beanFactory中。在完成之前,先預例項化那些單例bean(lazy-init為false的)。
3、IoC容器的初始化包括BeanDefinition的Resource定位,載入和註冊。
(1)、定位:使用BeanDefinitionReader讀取資源applicationContext.xml檔案。
(2)、載入:讀取xml檔案中定義的Bean,然後表示成IoC容器內部的資料結構beanDefinition,包括xml中定義的和component_scan自動掃描到的帶有@service,@controller,@dao註解的bean。
疑問?spring是用哪個類解析xml中定義的component_scan路徑並scan所有bean的?
(3)、註冊:向IoC容器註冊這些BeanDefinition的過程。通過呼叫BeanDefinitionRegistry介面的實現來完成的,這個註冊是把載入過程解析到的BeanDefinition向IoC容器進行註冊。在IoC內部是通過一個HashMap來儲存這些BeanDefinition資料的
4、IoC容器的初始化不包含Bean依賴注入的實現,一般依賴注入發生在應用第一次向容器通過getBean索取Bean時。但可以根據BeanDefinition資訊中的Lazyinit屬性來設定。即為false時,在容器初始化完成後,就預例項化。
預例項化時,先從父類容器中判斷是否有快取,父類沒有從子類容器判斷是否有快取。
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
synchronized (this.beanDefinitionMap) {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//父類中獲取。
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
}
}
5、Spring IoC對於不同scope的物件是怎麼管理的?
如果是single模式,那麼直接取容器中的例項,那如果是原型模式,是每次getBean的時候,建立新例項嗎?//TODO
6、為什麼用Spring IoC而不是用工廠模式?
使用工廠模式時,呼叫者仍然需要定位到工廠,使呼叫者和工廠耦合到一起。需要呼叫被呼叫者時直接IoC依賴注入。
7、幾種注入的不同@Resource,@Autowired,@Qualier?
TODO
8、IOC的注入方式?
參見這裡》Spring常用的三種注入方式 建構函式注入,Setter注入,基於註解的注入
參考: