容器是Spring框架的核心,Spring容器使用IOC管理全部組成應用系統的組件。Spring有兩種不一樣的容器:BeanFactory提供最簡單的容器,提供了最基礎的依賴注入支持,ApplicationContext創建在BeanFactory的基礎之上,提供了系統構架服務如從屬性文件中讀取文本信息,事件傳遞等。java
在Spring容器中拼湊Bean叫作裝配,裝配Bean的時候,你是在告訴容器須要哪些Bean以及容器如何使用依賴注入將它們配合在一塊兒。web
BeanFactory採用工廠設計模式,它的實現類負責建立和分發各類類型的Bean。spring
Spring中有幾種BeanFactory的實現,例如org.springframework.beans.factory.xml.XmlBeanFactory根據XML文件中的定義裝載Bean。(如今已經不建議使用)設計模式
ClassPathXmlApplicationContext:一種上下文,它從類路徑中載入上下文定義文件app
FileSystemXmlApplicationContext:一種應用上下文,它從文件系統中載入上下文文件框架
XmlWebApplicationContext:一種基於Spring的web應用系統上下文,從web應用上下文中載入上下文定義文件函數
public class TestMain { public static void main(String[] args) { //ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); ClassPathResource res = new ClassPathResource("applicationContext.xml"); BeanFactory factory=new XmlBeanFactory(res);//XmlBeanFactory如今已經不建議使用 Demo2 t=(Demo2) factory.getBean("demo2"); System.out.println(t.getPrice()); } }
Bean工廠從XML文件中讀取Bean的定義信息,可是此時尚未實例化Bean,Bean是被延遲載入到Bean工廠中的。而後調用getBean方法,工廠就會實例化Bean而且使用依賴注入開始設置Bean的屬性。測試
一個最基本的BeanFactory配置由一個或多個它所管理的Bean定義組成,在一個XmlBeanFactory中,根節點beans中包含一個或多個元素this
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="..." class="..."> ... </bean> <bean id="..." class="..."> ... </bean> ... </beans>
一個XmlBeanFactory中的Bean定義包括:spa
方向控制/依賴注入存在兩種主要的形式:
一、基於setter的依賴注入:是在調用無參構造函數或無參的靜態方法工廠方法實例化你的bean以後,經過調用你的bean上的setter方法實現的。Spring通常提倡使用基於setter方法的依賴注入。下面就這種方法距離:
構建Bean的實現類爲Demo1.java:
public class Demo1 { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Demo1() { System.out.println("調用無參構造函數"); } }
applicationContext.xml中的配置爲:
<bean id="demo1" class="com.Demo1"> <property name="name"> <value>xujian</value> </property> <property name="age"> <value>23</value> </property> </bean>
編寫測試類:
public class TestMain { public static void main(String[] args) { ApplicationContext factory=new ClassPathXmlApplicationContext("applicationContext.xml"); Demo1 t=(Demo1) factory.getBean("demo1"); System.out.println(t.getName()); } }
運行結果爲:
可見,經過setter方法,先是執行了該類的無參構造函數,而後調用setXXX方法來設置屬性。
二、基於構造函數的依賴注入:它是經過調用帶有許多參數的構造方法來實現的,每一個參數表示一個合做者或者屬性,下面就這種方法舉例
使用這種方法,須要在bean的實現類中添加有參構造函數
public class Demo2 { private String bookName; private int price; public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public Demo2(String bookName, int price) { System.out.println("執行有參構造函數!"); this.bookName = bookName; this.price = price; } }
對應applicationContext.xml的配置爲:
<bean id="demo2" class="com.Demo2" > <constructor-arg> <value>Java</value> </constructor-arg> <constructor-arg> <value>50</value> </constructor-arg> </bean>
編寫測試類:
public class TestMain { public static void main(String[] args) { ApplicationContext factory=new ClassPathXmlApplicationContext("applicationContext.xml"); Demo2 t=(Demo2) factory.getBean("demo2"); System.out.println(t.getBookName()); } }
執行結果爲:
Spring在缺省狀況下是單實例模式,在容器分配Bean的時候老是返回同一個實例。
測試以下:
public class TestMain { public static void main(String[] args) { ApplicationContext factory=new ClassPathXmlApplicationContext("applicationContext.xml"); Demo2 t1=(Demo2) factory.getBean("demo2"); Demo2 t2=(Demo2) factory.getBean("demo2"); System.out.println(t1==t2); } }
執行結果爲:
若是咱們想每次向上下文請求一個Bean的時候老是獲得一個不一樣的實例,則須要配置scope屬性,在原配置文件中scope的默認值是singleton,如今將其設置爲prototype
<bean id="demo2" class="com.Demo2" scope="prototype"> <constructor-arg> <value>Java</value> </constructor-arg> <constructor-arg> <value>50</value> </constructor-arg> </bean>
再次執行上面的測試程序,結果以下:
當一個Bean實例化的時候,可能須要作一些初始化的工做,刪除的時候須要作一些清理工做,在Bean的定義中設置本身的init-method和destroy-method並在xml文件中進行配置,這些方法就會在實例化建立或者銷燬的時候被調用。示例以下:
在Demo2類的定義中添加兩個函數
public void initialize() { System.out.println("執行了初始化函數!"); } public void close() { System.out.println("執行了銷燬函數!"); }
而後配置XMl文件
<bean id="demo2" class="com.Demo2" init-method="initialize" destroy-method="close"> <constructor-arg> <value>Java</value> </constructor-arg> <constructor-arg> <value>50</value> </constructor-arg> </bean>
運行測試程序
public class TestMain { public static void main(String[] args) { ApplicationContext factory=new ClassPathXmlApplicationContext("applicationContext.xml"); Demo2 t1=(Demo2) factory.getBean("demo2"); System.out.println(t1.getBookName()); t1.close(); } }
結果以下:
咱們能夠經過設置bean中的autowire屬性來實現自動裝配。有四種自動裝配的類型: