Spring系列教程三: Spring Ioc容器詳解
根據上一篇文章講解內容建立物件有以下兩種方式
一、主動去找資源通過例項化物件的方式,兩者之間有必然聯絡,應用獨立就變得比較難
IAccountService as=new AccountServiceImpl();
第二種、把獲取聯絡的工作較給了第三方,BeanFactory從而避免了和AccountDao之間的必然聯絡
IAccountService as=(IAccountService) Beanfactory.getBean("accountService");
為什麼要叫控制反轉?上面劃線的部分本來自己是有獨立的控制權限,想拿到那個物件就能拿到那個物件,但是它把自己的拿物件的權利轉交給 一個BeanFactory的工廠類,具體能拿到那個物件是由getBean裡面傳進來的引數決定。
控制反轉(Ioc)的概念
就是把建立物件的權利交給框架,是框架的重要特徵,只是面向物件中的一種設計概念,它包括依賴注入和依賴查詢,主要的作用是削減程式之間的耦合關係要是我們自己來寫控制反轉的話就是可以使用BeanFactory工廠模式(詳細參考上一篇部落格)來寫,但是在設計開發中很明顯會增加工作量,所以我們會把這個工作交給Spring來做,Spring中Spring Core是框架最基礎的部分,提供了Ioc的特性,Spring Ioc容器中主要包括BeanFactory 容器和ApplicationContext 容器
下面是使用Spring來進行控制反轉的示例
首先我們得下載Spring-framework的jar包,在pom檔案裡面進行下載
然後在根目錄下面resoure檔案中,建立一個xml配置檔案,要想降低依賴關係只有通過反射來建立物件,並且把這任務交給Spring來建立
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"> <!-- 上面的是約束,把物件的建立交給Spirng來管理,唯一標識id和全限定類名--> <bean id="accountService" class="com.ithema.jdbc.service.impl.AccountServiceImpl"></bean> <bean id="accountDao" class="com.ithema.jdbc.dao.impl.AccountDaoImpl"></bean> </beans>
下面是表現層的實現程式碼
package com.ithema.jdbc.ui;
import com.ithema.jdbc.dao.IAccountDao;
import com.ithema.jdbc.factory.Beanfactory;
import com.ithema.jdbc.service.IAccountService;
import com.ithema.jdbc.service.impl.AccountServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 模擬一個表現層,用於呼叫業務層
*/
public class Client {
public static void main(String[] args) {
/**
* 獲取Spring Ioc的核心容器,並且根據id獲取物件
*/
//IAccountService as=new AccountServiceImpl();
/* for (int i=0;i<5;i++){
IAccountService as=(IAccountService) Beanfactory.getBean("accountService");
System.out.println(as);
}*/
//as.saveAccount();
//1、獲取核心容器物件,new出來是它的實現類
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
//2、根據id獲取bean物件
IAccountService as= (IAccountService) ac.getBean("accountService");
IAccountDao adao= ac.getBean("accountDao",IAccountDao.class);//在IIAccountDao.class傳入位元組碼,讓位元組碼強轉
System.out.println(as);
System.out.println(adao);
as.saveAccount();
}
}
最後是輸出結果,成功的建立了兩個物件,並且執行了業務service層的方法
補充一個小的知識點ApplicationContext介面的幾個主要的實現類
* ApplicationContext的三個實現類 * ClassPathXmlApplicationContext,它可以載入類路徑下的配置檔案,要求配置在類路徑下,不在的話載入不了 * FileSystemXmlApplicationContext 它是可以載入磁碟下任意路徑的配置檔案(必須有訪問許可權) * AnnotationConfigApplicationContext 它是讀取註解建立容器 */
一樣能夠讀取到配置檔案,但是我們一般不建議這麼做,配置檔案一般都是和我們專案放在一起的,如果其他人不知道萬一給你刪除了怎麼辦??
核心容器的兩個介面引發出的兩個問題
* ApplicationContext:
* 它在建立核心容器採用的策略是立即載入的方式,也是就是說,有一讀取完馬上就穿件配置檔案的的物件
*
* BeanFactory:
* 它在建立核心容器時候的策略是採取延遲載入的方式,也就是說,什麼時候根據ID獲取物件了,什麼時候才真正建立物件
ApplicationContex建立物件情況演示如下
首先、我們要看到物件有沒有建立,需要去介面實現類裡面的建構函式輸出一句話,物件被建立了!!建立物件是通過例項化建構函式所得!!
BeanFactory建立物件情況演示如下
執行結果如下
繼續執行 step over
那麼在實際的開發中我們怎麼去選擇這兩種Ioc容器的兩種介面啦?具體情況具體分析
ApplicationContex適合於單例物件使用 ,BeanFactory使用於多例物件,但是在實際開發的過程中我們使用的是Applicati