1.IOC 控制反轉(Inversion of Control)
控制反轉是一種設計原則,用來降低代碼之間的耦合性。其中最常見的方式叫做依賴注入(DI)通過控制反轉,對象在被創建的時候,系統內所有對象將通過配置文件(XML,JavaCode,註解等...)配置的依賴的對象的引用傳遞給它。也可以說,依賴被注入到對象中。
容器(Container)容器的作用就是生成(生命週期開始時)、存放bean的實例並控制每個bean實例的生命週期 ,在適當的時候銷燬bean實例(生命週期結束時)。
Spring框架支持六個作用域,其中四個只有在使用Web感知的ApplicationContext時纔可用。也可以創建自定義範圍。
作用域 |
描述 |
singleton(單例) |
(默認)SpringIoC容器爲每個bean定義只創建一個對象實例 |
prototype(原型) |
每次調用都將創建對象實例。 |
request(請求) |
每次HTTP請求都會創建自己的bean實例。僅僅使用Web感知的ApplicationContext時纔可用。 |
session(會話) |
每個會話都會創建自己的bean實例。僅僅使用Web感知的ApplicationContext時纔可用。 |
application(應用) |
在ServletContext的生命週期中使用單個bean定義. 僅僅使用Web感知的ApplicationContext時纔可用。 |
Websocket(Websocket) |
將單個bean定義作用於WebSocket的生命週期。僅僅使用Web感知的ApplicationContext時纔可用。 |
IoC模式中,系統通過引入實現了IoC模式的IoC容器,即可由IoC容器來管理對象的生命週期、依賴關係等,從而使得應用程序的配置和依賴性規範與實際的應用程序代碼分離。其中一個特點就是通過文本的配置文件進行應用程序組件間相互關係的配置,而不用重新修改並編譯具體的代碼。
可以把IoC模式看作工廠模式的昇華,把IoC容器看作是一個大工廠,只不過這個大工廠裏要生成的對象都是在配置文件(XML,JavaCode,註解等...)中給出定義的。利用Java 的“反射”編程,根據配置文件(XML,JavaCode,註解等...)中給出的類定義生成相應的對象。從實現來看,以前在工廠模式裏寫死了的對象,IoC模式改爲配置文件(XML,JavaCode,註解等...),這就把工廠和要生成的對象兩者隔離,極大提高了靈活性和可維護性
1.1、BeanFactory
org.springframework.beans 和org.springframework.context 包是Spring 框架IOC容器的基礎。BeanFactory 接口提供了一種高級配置機制,能夠管理任何類型的對象。ApplicationContext 是BeanFactory的子接口。
BeanFacotry是spring中比較原始的Factory。如XMLBeanFactory就是一種典型的BeanFactory。原始的BeanFactory無法支持spring的許多插件,如AOP功能、Web應用等。
ApplicationContext接口,它由BeanFactory接口派生而來,ApplicationContext包含BeanFactory的所有功能,通常建議優先使用ApplicationContext
1 Resource resource = new FileSystemResource("beans.xml"); 2 BeanFactory factory = new XmlBeanFactory(resource);
1 ClassPathResource resource = new ClassPathResource("beans.xml"); 2 BeanFactory factory = new XmlBeanFactory(resource);
1 ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml", "applicationContext-part2.xml"}); 3 BeanFactory factory = (BeanFactory) context;
BeanFacotry 提供了六種方法供用戶調用
- boolean containsBean(String beanName) 判斷工廠中是否包含給定名稱的bean定義,若有則返回true
- Object getBean(String) 返回給定名稱註冊的bean實例。根據bean的配置情況,如果是singleton模式將返回一個共享實例,否則將返回一個新建的實例,如果沒有找到指定bean,該方法可能會拋出異常
- Object getBean(String, Class) 返回以給定名稱註冊的bean實例,並轉換爲給定class類型
- Class getType(String name) 返回給定名稱的bean的Class,如果沒有找到指定的bean實例,則拋出NoSuchBeanDefinitionException異常
- boolean isSingleton(String) 判斷給定名稱的bean定義是否爲單例模式
- String[] getAliases(String name) 返回給定bean名稱的所有別名
參考:Spring BeanFactory與FactoryBean的區別及其各自的詳細介紹於用法
org.springframework.context.ApplicationContext接口表示SpringIoC容器,負責實例化、配置和組裝bean。 BeanFactory 提供了配置框架和基本功能,ApplicationContext 添加了更多特定於企業的功能。ApplicationContext 是一個完整的BeanFactory 的擴展集
ApplicationContext 的實現類有FileSystemXmlApplicationContext、ClassPathXmlApplicationContext、AnnotationConfigApplicationContext。
ClassPathXmlApplicationContext 默認從類路徑加載配置文件,FileSystemXmlApplicationContext 默認從文件系統中裝載配置文件
和BeanFactory初始化相似,ApplicationContext的初始化也很簡單,如果配置文件放置在類路徑下,用戶可以優先使用ClassPathXmlApplicationContext實現類:
ApplicationContext ctx = new ClassPathXmlApplicationContext(“com/baobaotao/context/beans.xml”)
對於ClassPathXmlApplicationContext來說,”com/baobaotao/context/beans.xml”等同於”classpath: com/baobaotao/context/beans.xml”。
如果配置文件放置在文件系統的路徑下,則可以優先考慮使用FilySystemXmlApplicationContext實現類:
ApplicationContext ctx =new FileSystemXmlApplicationContext(“com/baobaotao/context/beans.xml”);
對於FileSystemXmlApplicationContext來說,“com/baobaotao/context/beans.xml”等同於“file:com/baobaotao/context/beans.xml”。
還可以指定一組配置文件,Spring會自動將多個配置文件在內存中”整合”成一個配置文件,如下所示:
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{“conf/beans1.xml”,”conf/beans2.xml”});
ApplicationContext的初始化和BeanFactory有一個重大的區別:BeanFactory在初始化容器時,並未實例化Bean,直到第一次訪問某個Bean時才實例目標Bean;而ApplicationContext則在初始化應用上下文時就實例化所有單實例的Bean。因此ApplicationContext的初始化時間會比BeanFactory稍長一些,不過稍後的調用則沒有”第一次懲罰”的問題。
WebApplicationContext 繼承了ApplicationContext接口,是ApplicationContext的擴展,它增加了WEB應用特性,還可以視圖解析、主題解析、映射,通過ServletContext與servlet關聯 ,WebApplicationContext被綁定在ServletContext上(通過ContextLoaderListener綁定),可以通過RequestContextUtils獲取WebApplicationContext。
WebApplicationContext是專門爲web應用準備的,他允許從相對於web根目錄的路勁中裝載配置文件完成初始化工作,從WebApplicationContext中可以獲得ServletContext的引用,整個Web應用上下文對象將作爲屬性放置在ServletContext中,以便web應用可以訪問spring上下文,spring中提供WebApplicationContextUtils的getWebApplicationContext(ServletContext src)方法來獲得WebApplicationContext對象
WebApplicationContext擴展了ApplicationContext.在 WebApplicationContext中定義了一個常量 ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,在上下文啓動時,WebApplicationContext以此爲鍵放置在ServletContext屬性列表中,
public static WebApplicationContext getWebApplicationContext(ServletContext sc) { return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); }
ConfigurableWebApplicationContext擴展了WebApplicationContext,它允許通過配置的方式實例化,同時設置兩個重要方法
setServletContext(ServletContext context) 爲spring設置web應用上下文,以便兩者整合
setConfigLocations(String[]locations) 設置Spring配置的文件地址
webApplicationContext初始化需要ServletContext,也就是說需要web容器前提下才能·完成啓動工作 可以通過在web.xml中配置自啓動Servlet或Web容器監聽來實現web容器的啓動
Spring分別提供啓動WebApplicationContext的servlet和Web容器監聽器
org.springframework.web.context.ContextLoaderListener
org.springframework.web.context.ContexLoaderServlet 此方法目前以廢棄
!--從類路徑下加載Spring配置文件,classpath特指類路徑下加載--> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:smart-context.xml </param-value> </context-param> <!--負責啓動spring容器的監聽器 還可以聲明自啓動的Servlet ContextLoaderServlet--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
如果使用@Configuration的java類提供配置信息的配置 web.xml配置修改如下
<!--通過指定context參數,讓Spring使用AnnotationConfigWebApplicationContext啓動容器而非XmlWebApplicationContext 默認沒配置時是使用XmlWebApplicationContext--> <context-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value> </context-param> <!--指定標註了@Configuration的類,多個可以用逗號分隔--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>com.example.Car,com.example.Boss</param-value> </context-param> <!--監聽器將根據上面的配置使用AnnotationConfigWebApplicationContext 根據contextConfigLocation 指定的配置類啓動Spring容器--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
1.4 配置元數據
SpringIoC容器使用一種配置元數據。此配置元數據展示了Spring 容器如何在應用程序中實例化、配置和組裝對象。
Spring容器支持基於XML的配置元數據配置,Spring2.5引入了對基於註釋的配置元數據的支持,從Spring3.0開始,Spring JavaConfig 項目提供的許多特性成爲核心Spring框架的一部分,引入了對基於Java的配置元數據的支持。
基於XML的配置元數據將這些bean配置爲在頂層元素<beans/>內部的<bean/>元素。Java配置通常在帶有@Configuration註釋的類中使用帶@Bean註釋的方法。
基於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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="..." class="..."> ① ② <!-- collaborators and configuration for this bean go here --> <!-這個bean的協作者(引用其他的bean)和配置在這裏-> </bean> <bean id="..." class="..."> <!-- collaborators and configuration for this bean go here --> <!-這個bean的協作者和配置在這裏-> </bean> <!-- more bean definitions go here --> <!-更多的bean配置在這裏-> </beans>
<bean>中 id屬性是標識單個bean定義的字符串,class屬性定義Bean的類型,並使用完全限定的類名稱。
基於Java的配置元數據的基本結構:
@Configuration public class SpringConfig { @Bean public Piano piano(){ return new Piano(); } @Bean(name = "counter") public Counter counter(){ return new Counter(12,"Shake it Off",piano()); } }