ApplicationContext可以被看作Spring的容器,它是繼承自BeanFactory的。BeanFactory是訪問容器的根接口,提供了必要的配置框架和基礎功能,而ApplicationContext提供了更多的企業級功能和更加豐富的功能。
1 容器概覽
org.springframework.context.ApplicationContext接口代表了SpringIoC容器,它用於實例化、配置和組合bean。通過讀取配置元數據,容器就能獲取到實例化、配置和組合對象的指令。XML、註解或Java代碼中可以存在配置元數據。
Spring提供了幾種“開箱即用”的ApplicationContext接口實現。在單獨的應用程序中,創建一個ClassPathXmlApplicatlionContext或FileSystemXmlApplicationContext的實例是很普遍的。不過,在大部分應用場景中,不需要顯式地實例化一個或多個IoC實例。
應用系統的類和配置元數據是結合在一起的,所以在ApplicationContext創建和初始化之後,應用系統就已經配置完畢且可以執行了。
2 配置元數據
IoC容器採用配置元數據的方式。這種配置元數據表明了容器需要如何實例化、配置和組織對象。
Spring配置至少包含一個bean定義。由基於XML的配置元數據可知,頂層<beans><beans/>中配置的即爲bean元素。Java配置通常在一個類中使用@Bean註解方法。
這些根據實際對象定義的bean組成了應用程序。特別是在定義服務層對象、數據訪問層對象(DAO)、表現層對象(比如Struts的Action實例)等時候。
下面的例子說明了一個基於XML配置元數據的基礎構造。
- <?xml version="1.0" encoding="UTF-8"?>
- <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.xsd">
- <bean id="..." class="...">
- <!—屬性和配置 -->
- </bean>
- <bean id="..." class="...">
- <!—屬性和配置 -->
- </bean>
- <!—更多的bean定義-->
- </beans>
id屬性是一個用來識別各個bean定義的字符串。class屬性定義了bean的類型,而且使用類名的全稱。id屬性的值引用的是對象。
3 容器的實例化
Spring容器的實例化過程很直接,傳遞給ApplicationContext構造器的參數即爲配置元數據相關資源的路徑。
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
下面的例子即爲服務層對象services.xml配置文件:
- <?xml version="1.0" encoding="UTF-8"?>
- <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.xsd">
- <!-- services -->
- <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
- <property name="accountDao" ref="accountDao"/>
- <property name="itemDao" ref="itemDao"/>
- <!—其它屬性和配置 -->
- </bean>
- <!—更多bean定義 -->
- </beans>
下面即爲數據訪問對象daos.xml配置文件:
- <?xml version="1.0" encoding="UTF-8"?>
- <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.xsd">
- <bean id="accountDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
- <!—其它屬性和配置-->
- </bean>
- <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
- <!--其它屬性和配置-->
- </bean>
- <!—更多bean定義 -->
- </beans>
在前述例子中,服務層包含類PetStoreServiceImpl,以及兩個數據訪問對象JpaAccountDao和JpaItemDao。name屬性表示bean的名稱,ref屬性表示引用另一個bean的名字。id和ref的關係即爲依賴關係。
在一個龐大的系統中,如果將所有的bean定義存放在一個xml文件中,那麼維護起來將是一場噩夢。Spring提供了一種方式可以解決這個問題,即將不同業務層的配置文件放到不同的xml文件中,然後在一個xml文件中引入其它所有的配置文件。main.xml示例如下:
- <beans>
- <import resource="services.xml"/>
- <import resource="resources/messageSource.xml"/>
- <import resource="/resources/themeSource.xml"/>
- <bean id="bean1" class="..."/>
- <bean id="bean2" class="..."/>
- </beans>
這個例子中,從三個文件裏引入了外部bean定義:services.xml,messageSource.xml和themeSource.xml。所有的路徑都是相對於main.xml的,因此services.xml必須與main.xml在相同路徑下,而其它兩個xml文件所在的文件夾resources路徑必須與main.xml相同。可見,前面的那一個斜槓被忽略了,因爲這裏必須是相對路徑,最好不要在路徑前面加上斜槓。
4 容器的使用
ApplicationContext是一個高級工廠接口,它維護着不同的bean及其依賴的註冊。使用T getBean(String name, Class<T> requiredType)可以查詢到已實例化的bean。可以通過ApplicationContext來讀取和訪問定義的bean。
- // 創建和配置bean
- ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
- // 查詢配置的實例
- PetStoreService service = context.getBean("petStore", PetStoreService.class);
- // 使用配置的實例
- List<String> userList = service.getUsernameList();
getBean用來查詢bean實例,ApplicationContext還有其它查詢bean實例的方法,理想情況下你不會用到它們。實際上,應用代碼中不應該有getBean方法,這樣就不用依賴Spring的API,比如Spring與Web框架的集成就提供了相應的依賴注入,而不需要顯式地去調用getBean方法。