IoC全稱爲控制反轉(Inverse of Control),也叫依賴注入,是spring容器的內核,AOP、事務等都依賴於此技術。IoC說白了,就是將對象與對象之間的依賴關係從代碼中轉移到spring的配置文件中(默認爲ApplicationContext.xml 也能夠自定義名字),從而由spring進行管理。這樣的好處就是下降了對象與對象之間的依賴。IoC的工做原理就是利用Java的反射功能實例化對象與對象的依賴。除此以外,IoC容器還提供了對象的實例緩存、生命週期管理、對象實例代理、事件發佈、資源裝載等高級功能。java
BeanFactory接口也就是你們熟知的Bean工廠,它是spring框架最核心的接口,它提供了高級的IoC配置機制,能夠管理任何不一樣類型的Java對象。ApplicationContext接口是繼BeanFactory接口以外,另外一個重要的接口。它的功能是創建在BeanFactory接口之上的。它除了已有的功能外,還提供國際化支持和框架事件等更多面嚮應用的功能。對於二者的區別用最直觀最簡介的方式來講就是BeanFactory是Spring框架的內核,它是給Spring用的,而ApplicationContext接口是給使用Spring框架的開發者用的。web
BeanFactory是一個類工廠,但它和通常的類工廠不一樣,通常的類工廠是實例化一個類或幾個類,而BeanFactory是個超級工廠,能夠建立管理各類類。全部被BeanFactory管理的對象在Spring中統稱爲Bean.下面咱們初始化BeanFactory工廠,並在工廠中獲取某個對象。spring
spring配置文件: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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 給car的全部屬性賦值 --> <bean id="car" class="com.xiaobai.spring.mark.Car" p:brand="衆泰T600S" p:color="白色" p:speed="120"></bean> </beans>
實體類Car.javasession
public class Car { /** 品牌 */ private String brand; /** 顏色 */ private String color; /** 速率 */ private int speed; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } @Override public String toString() { return "Car{" + "brand='" + brand + '\'' + ", color='" + color + '\'' + ", speed=" + speed + '}'; } }
測試類CarTest.javaapp
public class CarTest { /** * new 方式實例化car對象 */ @Test public void newCreateCar() { Car car = new Car(); car.setBrand("捷豹xjl"); car.setColor("黑色"); car.setSpeed(200); System.out.println(car); } /** * BeanFactory 方式實例化car對象 */ @Test public void beanFactoryCreateCar() { ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); Resource resource = resourcePatternResolver.getResource("classpath:xiaobai/beans.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource); Car car = beanFactory.getBean("car", Car.class); System.out.println(car); } /** * applicationContext 方式實例化car對象 */ @Test public void applicationContextCreateCar() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:xiaobai/beans.xml"); Car car = applicationContext.getBean("car", Car.class); System.out.println(car); } }
XmlBeanFactory經過Resource裝載Spring配置信息並啓動IoC容器,而後經過BeanFactory中的getBean()方法從IoC容器中獲取Bean.根據Spring的內部機制,啓動IoC容器時,並不會初始化配置文件中的Bean.當第一次調用getBean()時初始化。對於單例的Bean來講,BeanFactory會緩存Bean實例,在第二次調用getBean()時,直接從IoC容器的緩存中獲取Bean實例。接下來咱們經過下面的例子來證實BeanFactory的緩存機制。框架
BeanFactory的緩存測試ide
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); Resource resource = resourcePatternResolver.getResource("classpath:xiaobai/beans.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource); Car car1 = beanFactory.getBean("car", Car.class); Car car2 = beanFactory.getBean("car", Car.class); System.out.println(car1); System.out.println(car2);
上述代碼咱們從IoC容器中獲取了兩個Car,經過輸出對象的內存地址信息來判斷這兩個car是否爲同一個測試
輸出結果ui
com.xiaobai.spring.mark.Car@1d96f4b5 com.xiaobai.spring.mark.Car@1d96f4b5
經過輸出結果證實了咱們以前所說的,BeanFactory的緩存機制。但在各別狀況下咱們不但願它有緩存,咱們但願每次訪問時返回的都是一個新的對象。那怎麼辦呢。咱們能夠經過scope屬性來配置。
beanx.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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 給car添加scope屬性並值設置爲prototype --> <bean id="car" class="com.xiaobai.spring.mark.Car" p:brand="衆泰T600S" p:color="白色" p:speed="120" scope="prototype"></bean> </beans>
輸出結果
com.xiaobai.spring.mark.Car@6ecf829d com.xiaobai.spring.mark.Car@79884a40
經過結果咱們看,經過給Bean設置scope="prototype"時,IoC容器每次返回的都是一個新對象了,若是想每次返回的都是同一個對象,能夠設置爲scope="singleton",默認不設置scope屬性時scope="singleton"
Spring3.0之後支持類註解的配置方式,能夠經過@Configuration註解爲Spring提供配置信息,Spring爲配置的註解類提供了一個專門的實現類AnnotationConfigApplicationContext,下面咱們來看一下怎麼來加載配置信息
Beans.java
@Configuration public class Beans { @Bean(name = "car") public Car buildCar() { Car car = new Car(); car.setBrand("東風標誌508"); car.setColor("白色"); car.setSpeed(300); return car; } }
測試用例
/** * @Configuration 方式實例化car對象 */ @Test public void configurationCreateCar() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Beans.class); Car car = applicationContext.getBean("car", Car.class); System.out.println(car); }
輸出結果
Car{brand='東風標誌508', color='白色', speed=300}
WebApplicationContext接口是Spring專門爲Web應用準備的,它繼承了ApplicationContext接口,併爲Bean的scope屬性增長了三個值分別是request、session、globalSession.它容許從Web根目錄的路徑中裝載配置文件,完成初始化工做。由於它是爲Web服務的,因此它必須依賴於Web容器。根據Web項目開發經驗,咱們應該在web.xml配置自啓動的Servlet或者Web容器監聽器,來配置Web項目開發環境。Spring爲這兩種都提供了相應的類,來啓動Spring容器。它們分別爲org.springframework.web.context.ContextLoaderListener和org.springframework.web.context.ContextLoaderServlet.咱們能夠根據這兩種中的任何一種方式來啓動WebApplicationContext。雖然兩種沒有什麼太大的區別,均可以啓動WebApplicationContext,可是隻有Servlet2.3以上的版本的Web容器才支持Web容器的監聽器。(包括當前版本),因此能夠根據項目須要配置啓動WebApplicationContext的方式。下面咱們來看一下具體的配置代碼
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- 下面的代碼是選擇Spring配置文件的路徑,也能夠定義Spring配置文件的名字 若是不配置Spring默認在項目根目錄下查找applicationContext.xml文件 --> <context-param> <param-name>contextConfigLocation</param-name> <!-- 若是配置多個文件能夠用逗號分隔,也能夠用資源前綴的方式配置 ? : 匹配文件名中的一個字符 * : 匹配文件名中的任意個字符 ** : 匹配多層路徑 classpath:com/t?st.xml 匹配com類路徑下的com/tast.xml、tbst.xml 等 classpath:com/*.xml 匹配com類路徑下的全部xml文件 classpath:com/**.xml 匹配com類路徑及其子目錄下的全部xml文件 --> <param-value>classpath:beans.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
在SpringIoC容器中一個Bean對應配置文件中的一個<bean>,id爲這個Bean的名稱,經過容器的getBean()方法獲取對應的Bean。id在IoC容器中必須是惟一的,它的命名還要知足XML對id的命名規範:必須以字母開始,後機能夠是字母、數字、連字符、下劃線、等。可是,在特殊狀況下,咱們須要特別的名字,那id就不容許了。這時咱們能夠用name屬性。name屬性沒有字符限制,幾乎可使用任何字符,並能夠設置多個名字。以下所示
<bean name="#1, $2" class="com.xiaobai.spring.mark.Car" p:brand="衆泰T600S" p:color="白色" p:speed="120"/>
Spring配置文件雖然不容許出現兩個id的<bean>,但卻能夠出現兩個name的<bean> 若是有多個name相同的<bean> 獲取時,將返回最後聲明的那個Bean,緣由是後面的<bean>覆蓋了前面的<bean>.若是id和name兩個屬性都未指定,Spring自動將class作爲Bean的名稱。以下所示
<bean class="com.xiaobai.spring.mark.Car" p:brand="衆泰T600S" p:color="白色" p:speed="120"/>
@Test public void applicationContextCreateCar() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:xiaobai/beans.xml"); Car car = applicationContext.getBean("com.xiaobai.spring.mark.Car", Car.class); System.out.println(car); }
執行結果
Car{brand='衆泰T600S', color='白色', speed=120}