提到spring,第一印象就是DI與IOC,雖然有概念上的解釋,但是要理解這些概念還是需要動手進(jìn)行試驗
。如果要深入了解spring的原來,那么最先了解得就應(yīng)該是spring容器。Spring提供了兩種類型的IOC容
器實現(xiàn):
1.beanFactory: IOC 容器的基本實現(xiàn)。
2.ApplicationContext: 提供了更多的高級特性,是beanFactory的子接口。
在spring的應(yīng)用中,經(jīng)常見到的代碼就是如下典型的從容器中獲取bean實例的代碼:
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
OrderService service = (OrderService)ctx.getbean("personService");
第一行代碼就是創(chuàng)建一個IOC容器的實例。BeanFactory、ApplicationContext只是接口,在應(yīng)用中
需要實例化其實現(xiàn)類。ApplicationContext實現(xiàn)類有以下三種是經(jīng)常要用到的:
ClassPathXmlApplicationContext: 從 classpath 下加載配置文件
FileSystemXmlApplicationContext: 從文件系統(tǒng)中加載配置文件
XmlWebApplicationContext: 只能用于 web 應(yīng)用
無論使用何種方式, 配置文件時相同的。但是由于ApplicationContext提供了更多的附加功能,比
如它提供了文本信息解析工具、載入資源的通用方法等等,所以使用的時候大部分都是用該接口。在web
應(yīng)用中通常都是通過ClassPathXmlApplicationContext去類路徑下加載配置文件,生成一個IOC容器并管
理配置文件中配置的bean。
Spring提供了強(qiáng)大的IOC容器來管理組成應(yīng)用程序中的bean(組件)。要利用容器提供的服務(wù),就必須
配置bean,讓這些bean運(yùn)行在Spring IOC容器中。為了讓Spring IOC 容器能夠?qū)ean進(jìn)行實例化,每個
bean 都應(yīng)該提供一個唯一的名稱和一個全限定類名。例如下面三種方式實例化bean:
1.使用類構(gòu)造器實例化
<bean id="orderService" class="cn.itcast.OrderServiceBean"/>
2.使用靜態(tài)工廠方法實例化
<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容易直接根據(jù)配置文件中的class屬性通過反射創(chuàng)建一個實例,使用的是該類的默
認(rèn)構(gòu)造方法。第二種則是調(diào)用class指定的工廠類的工廠方法,來返回一個相應(yīng)的bean實例,值得注意的
是工廠類的方法是靜態(tài)方法,所以不用產(chǎn)生工廠本身的實例。而第三種則不同,它除了配置與第二種相
同外,唯一的不同就是方法不是靜態(tài)的,所以創(chuàng)建bean的實例對象時需要先生成工廠類的實例。
實例了bean對象時,需要對其中的屬性也進(jìn)行賦值,這時就是經(jīng)常被提及的依賴注入。對bean的每
個簡單類型的屬性來說,可以為其制定<value>元素。Spring會嘗試將值轉(zhuǎn)換為該屬性的聲明類型。比較
常用的有:
1.setter注入使用<property>元素,使用name屬性指定bean的屬性名稱。優(yōu)點(diǎn): setter 方法可以
自動生成,簡單。缺點(diǎn): 組件使用者或許會忘記給組件注入它需要的依賴; 在第一次注入后,依賴可能
會因為 setter 方法的調(diào)用而被修改。
2.構(gòu)造器注入在 <constructor-arg>元素里聲明屬性,因為構(gòu)造器的參數(shù)是基于位置的, 所以
<constructor-arg>中沒有name屬性。優(yōu)點(diǎn): 解決了setter注入的缺點(diǎn)。缺點(diǎn): 需通過參數(shù)位置來確定參
數(shù); 若組件有多個依賴需要注入, 會導(dǎo)致構(gòu)造器參數(shù)列表非常冗長。
IOC容器里可能會聲明很多的bean,這些bean之間的依賴關(guān)系通常會比較復(fù)雜。使用setter注入并不
能保證屬性一定會被注入。spring通過依賴檢查來檢查屬性:
1.Spring 的依賴檢查特性可以檢查bean上的某些類型的所有屬性是否被設(shè)置。
2.Spring 的依賴檢查特性只需在<bean>的dependency-check 屬性里指定依賴檢查模式即可。
3.Spring 的依賴檢查特性只能檢查屬性是否被設(shè)置,但對設(shè)置的屬性值是 null 的情況則無能為力
。
4.Spring 的依賴檢查特性只對屬性是否通過 setter 方法設(shè)置進(jìn)行檢查。 所以, 即使通過構(gòu)造器
注入,依然會拋出異常。
以上是通過配置文件來檢查,另外一種方式就是通過@Required注解檢查屬性。Spring的依賴檢查特
性只能檢查某些類型的所有屬性。不能只針對個別屬性進(jìn)行檢查。
RequiredAnnotationbeanPostProcessor 是Spring的bean后置處理器,它檢查所有具有@Required注解的
屬性是否已被設(shè)置。bean后置處理器是一種特殊類型的Spring bean,它能夠在每個bean實例化后執(zhí)行一
些額外的工作。要激活bean后置處理器來進(jìn)行屬性檢查,必須在Spring IOC容器里注冊它。
RequiredAnnotationbeanPostProcessor只能檢查屬性是否被設(shè)置,但對設(shè)置的屬性值是 null 的情況則
無能為力。