Spring系列之裝配Bean

1、概述

  容器是Spring框架的核心,Spring容器使用IOC管理全部組成應用系統的組件。Spring有兩種不一樣的容器:BeanFactory提供最簡單的容器,提供了最基礎的依賴注入支持,ApplicationContext創建在BeanFactory的基礎之上,提供了系統構架服務如從屬性文件中讀取文本信息,事件傳遞等。java

  在Spring容器中拼湊Bean叫作裝配,裝配Bean的時候,你是在告訴容器須要哪些Bean以及容器如何使用依賴注入將它們配合在一塊兒。web

2、裝配Bean

  2.1  使用XML裝配

  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());
    }
}

  2.2  添加一個bean

  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

  • classname:一般是bean的真正的實現類,可是若是一個bean使用一個靜態工廠方法所建立而不是被普通的構造函數建立,那麼這就是工廠類的classname
  • bean行爲配置元素:它聲明這個bean在容器中的行爲方式,好比自動裝配模式、依賴檢查模式、初始化和析構方法
  • 構造函數的參數和新建立bean所須要的屬性:好比池的大小限制
  • 和這個bean工做相關的其餘bean:好比它的合做者

  方向控制/依賴注入存在兩種主要的形式:

  一、基於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());
    }
}

  執行結果爲:

  

  2.3  原型與單實例

  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>

  再次執行上面的測試程序,結果以下:

  

  2.4  實例化與銷燬

  當一個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();
    }
}

  結果以下:

  

   2.5  自動裝配  

  咱們能夠經過設置bean中的autowire屬性來實現自動裝配。有四種自動裝配的類型:

  • byName:試圖在容器中尋找和須要自動裝配的屬性名相同的Bean

  

  • byType:在容器中尋找與須要自動裝配的屬性類型相同的Bean

  

  • constructor:在容器中尋找與須要自動裝配的Bean的構造函數參數一致的一個或多個Bean
  • null:無自動裝配模式,Bean的引用必需要經過ref元素定義
相關文章
相關標籤/搜索