控制反轉容器(IoC Container)是Spring的一個重要基礎功能,不喜歡新名詞的同窗,姑且理解爲組件裝配容器.java
要理解Spring的設計精神,先來看看Spring的設計初衷.git
先看看沒有Spring以前,咱們怎麼作.
以一個現實的狀況說明.你們應該都有過購買手機的經歷.
收到手機後,打開包裝, 給手機裝上SIM卡,裝上電池,開機 ... github
咱們用java面向對象的思想作設計:
手機,SIM卡,電池, 這是三個對象,也可稱爲實體,物體,組件,零件
名稱不重要,反正這是三個東西,天然對應三個java 對象.
1, Battery.javaspring
package demo; public class Battery{ private String power; public Battery(String power){ this.power = power; } public String getPower(){ return this.power; } }
2, Simcard.javawindows
package demo; public class Simcard{ private String number; public Simcard(String number){ this.number = number; } public String getNumber(){ return this.number; } }
3, Mobile.java數組
package demo; public class Mobile{ private String brand; private Battery battery; private Simcard simcard; public Mobile(String brand){ this.brand = brand; } public void setBattery(Battery battery){ this.battery = battery; } public void setSimcard(Simcard simcard){ this.simcard = simcard; } public void poweron(){ System.out.println("Mobile: " + this.brand + " powered on"); System.out.println("Battery: " + this.battery.getPower() ); System.out.println("Simcard: " + this.simcard.getNumber() ); } }
4, 運行程序 Main.javagradle
package demo; public class Main{ public static void main(String[] args) { //建立零件 Mobile mobile = new Mobile("XiaoMI1"); Battery battery = new Battery("2000mA"); Simcard simcard = new Simcard("13612345678"); //組裝零件 mobile.setBattery(battery); mobile.setSimcard(simcard); //使用 mobile.poweron(); } }
以上程序不使用Spring,運行良好.
由於這裏只有三個零件,建立和組裝都沒有問題.
若有一個設備由1000個零件,建立和組裝過程就很繁瑣.
試想,咱們網購了一輛山地自行車,要把它裝配起來,咱們首先會看貨品清單和裝配說明書.this
Spring 容器就是爲建立和組裝零件而設計的.設計
在介紹Spring 容器以前, 先介紹一下容器的概念,初學者會對容器概念感到陌生.
現實生活中,裝有糖果的盒子就是容器,Java裏的容器和現實生活相似,只不過裝的是對象實例.
這裏對 Main.java 作些修改以解釋容器概念
4, 運行程序 Main.javacode
package demo; public class Main{ public static void main(String[] args) { //建立容器 Object[] container = new Object[3]; //建立和組裝實例 Mobile mob = new Mobile("XiaoMI1"); Battery bat = new Battery("2000mA"); Simcard sim = new Simcard("13612345678"); mob.setBattery(bat); mob.setSimcard(sim); //放入容器 container[0] = mob; container[1] = bat; container[2] = sim; //從容器中獲取實例 Mobile mobile = (Mobile) container[0]; mobile.poweron(); } }
以上程序建立數組做爲容器, 建立和組裝實例後放入容器, 使用時,從容器中獲取實例.
這個程序看起來有些畫蛇添足,確體現了容器的主要特性.
這裏,咱們手動完成了 建立容器->建立和組裝實例->放入容器的工做.
使用Spring後,這些工做就能夠由Spring來完成.
這裏,咱們使用對象數組做爲容器, 經過數字下標獲取對象, Spring 使用ConcurrentHashMap 做爲容器, 經過字符串ID獲取對象. (事實上ConcurrentHashMap 內部也是把對象包裝一下放到數組裏)
這裏,零件之間的裝配關係經過人工完成,而Spring經過配置文件來描述零件之間的裝配關係.
Spring的配置文件使用XML格式描述組件清單和裝配關係,這個配置文件至關於現實生活中的貨品清單和裝配說明書.
使用Spring容器時,須要一個配置文件(貨品清單) manifest.xml
5, manifest.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-4.0.xsd"> <bean id="battery1" class="demo.Battery"> <constructor-arg name="power" value="3000mA" /> </bean> <bean id="simcard1" class="demo.Simcard"> <constructor-arg name="number" value="13512345678" /> </bean> <bean id="mobile1" class="demo.Mobile"> <constructor-arg name="brand" value="Xiaomi" /> <property name="Simcard" ref="simcard1"/> <property name="Battery" ref="battery1"/> </bean> </beans>
這裏的bean 就是對象實例的意思,java裏全部對象實例均可稱爲bean
這個配置文件,簡單的說就是一個bean的列表. 每一個bean經過XML配置其建立初始值或是裝配對象. id屬性,是爲了之後便於從容器中獲取.
這個配置文件裏battery1,simcard1 咱們設定的構造參數,而mobile1, 咱們設定了構造參數的同時還裝配了具體的Battery和Simcard.
4, 運行程序 Main.java( 使用Spring)
package demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main{ public static void main(String[] args) { ApplicationContext context= new ClassPathXmlApplicationContext("manifest.xml"); Mobile mobile = (Mobile) context.getBean("mobile1"); System.out.println("************************"); mobile.poweron(); } }
這裏的context, 簡單的理解就是對象容器, Spring 經過分析配置文件完成對象建立,裝配的工做.
使用時,經過ID獲取容器對象.
Spring容器經過配置文件來描述零件清單和裝配關係,裝配關係變更時,修改配置便可,不用從新編譯代碼.
對於簡單的例子,看不出Spring容器的優點.
當對於零件不少,裝配關係複雜多變的系統,就能體現Spring的優點.
Spring 容器除了使用xml來配置,還可使用註解(annotation)來配置. 註解配置,這裏不在展開細說,總之,二者的功能是同樣的,看我的喜愛使用.
運行源代碼
git clone https://github.com/huanghq/SpringContainerExample.git
cd SpringContainerExample/
./gradlew run
(windows 用戶:gradlew.bat run)
************************ Mobile: Xiaomi powered on Battery: 3000mA Simcard: 13512345678
運行源代碼要求Java1.7 環境,支持跨平臺.
使用gradle 下載依賴包,編譯運行.不熟悉gradle的同窗不要緊.
只需專一上述java文件和配置文件,
第一次運行須要下載gradle和java依賴包,有些慢,耐心等待.
對控制反轉(IOC)概念感興趣的同窗,參看下文:
Java開發中的依賴注入(DI)和控制反轉(IOC)