Spring中bean的例項化方式與IOC容器總結
提到spring,第一印象就是DI與IOC,雖然有概念上的解釋,但是要理解這些概念還是需要動手進行試驗。如果要深入瞭解spring的原來,那麼最先了解得就應該是spring容器。Spring提供了兩種型別的IOC容器實現:
1.beanFactory: IOC 容器的基本實現。
2.ApplicationContext: 提供了更多的高階特性,是beanFactory的子介面。
在spring的應用中,經常見到的程式碼就是如下典型的從容器中獲取bean例項的程式碼:
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
OrderService service = (OrderService)ctx.getbean("personService");
第一行程式碼就是建立一個IOC容器的例項。BeanFactory、ApplicationContext只是介面,在應用中需要例項化其實現類。ApplicationContext實現類有以下三種是經常要用到的:
ClassPathXmlApplicationContext: 從 classpath 下載入配置檔案
FileSystemXmlApplicationContext: 從檔案系統中載入配置檔案
XmlWebApplicationContext: 只能用於 web 應用
無論使用何種方式, 配置檔案時相同的。但是由於ApplicationContext提供了更多的附加功能,比如它提供了文字資訊解析工具、載入資源的通用方法等等,所以使用的時候大部分都是用該介面。在web應用中通常都是通過ClassPathXmlApplicationContext去類路徑下載入配置檔案,生成一個IOC容器並管理配置檔案中配置的bean。
Spring提供了強大的IOC容器來管理組成應用程式中的bean(元件)。要利用容器提供的服務,就必須配置bean,讓這些bean執行在Spring IOC容器中。為了讓Spring IOC 容器能夠對bean進行例項化,每個bean 都應該提供一個唯一的名稱和一個全限定類名。例如下面三種方式例項化bean:
1.使用類構造器例項化
<bean id="orderService" class="cn.itcast.OrderServiceBean"/>
2.使用靜態工廠方法例項化
<bean id="personService" class="cn.itcast.service.OrderFactory" factory-method="createOrder"/>
public class OrderFactory {
public static OrderServiceBean createOrder(){
return new OrderServiceBean();
}
}
3.使用例項工廠方法例項化:
<bean id="personServiceFactory" class="cn.itcast.service.OrderFactory"/>
<bean id="personService" factory-bean="personServiceFactory" factory-method="createOrder"/>
public class OrderFactory {
public OrderServiceBean createOrder(){
return new OrderServiceBean();
}
}
第一種方法,IOC容易直接根據配置檔案中的class屬性通過反射建立一個例項,使用的是該類的預設構造方法。第二種則是呼叫class指定的工廠類的工廠方法,來返回一個相應的bean例項,值得注意的是工廠類的方法是靜態方法,所以不用產生工廠本身的例項。而第三種則不同,它除了配置與第二種相同外,唯一的不同就是方法不是靜態的,所以建立bean的例項物件時需要先生成工廠類的例項。
例項了bean物件時,需要對其中的屬性也進行賦值,這時就是經常被提及的依賴注入。對bean的每個簡單型別的屬性來說,可以為其制定<value>元素。Spring會嘗試將值轉換為該屬性的宣告型別。比較常用的有:
1.setter注入使用<property>元素,使用name屬性指定bean的屬性名稱。優點: setter 方法可以自動生成,簡單。缺點: 元件使用者或許會忘記給元件注入它需要的依賴; 在第一次注入後,依賴可能會因為 setter 方法的呼叫而被修改。
2.構造器注入在 <constructor-arg>元素裡宣告屬性,因為構造器的引數是基於位置的, 所以 <constructor-arg>中沒有name屬性。優點: 解決了setter注入的缺點。缺點: 需通過引數位置來確定引數; 若元件有多個依賴需要注入, 會導致構造器引數列表非常冗長。
IOC容器裡可能會宣告很多的bean,這些bean之間的依賴關係通常會比較複雜。使用setter注入並不能保證屬性一定會被注入。spring通過依賴檢查來檢查屬性:
1.Spring 的依賴檢查特性可以檢查bean上的某些型別的所有屬性是否被設定。
2.Spring 的依賴檢查特性只需在<bean>的dependency-check 屬性裡指定依賴檢查模式即可。
3.Spring 的依賴檢查特性只能檢查屬性是否被設定,但對設定的屬性值是 null 的情況則無能為力。
4.Spring 的依賴檢查特性只對屬性是否通過 setter 方法設定進行檢查。 所以, 即使通過構造器注入,依然會丟擲異常。
以上是通過配置檔案來檢查,另外一種方式就是通過@Required註解檢查屬性。Spring的依賴檢查特性只能檢查某些型別的所有屬性。不能只針對個別屬性進行檢查。RequiredAnnotationbeanPostProcessor 是Spring的bean後置處理器,它檢查所有具有@Required註解的屬性是否已被設定。bean後置處理器是一種特殊型別的Spring bean,它能夠在每個bean例項化後執行一些額外的工作。要啟用bean後置處理器來進行屬性檢查,必須在Spring IOC容器裡註冊它。RequiredAnnotationbeanPostProcessor只能檢查屬性是否被設定,但對設定的屬性值是 null 的情況則無能為力。