輕鬆理解Java Spring 核心功能之一: 控制反轉容器(IoC Container)

控制反轉容器(IoC Container)是Spring的一個重要基礎功能,不喜歡新名詞的同窗,姑且理解爲組件裝配容器.java

爲何須要Spring容器 ?(Why Spring Container)

要理解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() );

    }
}

不使用Spring 容器

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容器

使用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)

相關文章
相關標籤/搜索