Spring系列之裝配Bean


一、概述

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

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

二、裝配Bean

  2.1  使用XML裝配

  BeanFactory采用工廠設計模式,它的實現類負責創建和分發各種類型的Bean。

  Spring中有幾種BeanFactory的實現,例如org.springframework.beans.factory.xml.XmlBeanFactory根據XML文件中的定義裝載Bean。(現在已經不建議使用)

  ClassPathXmlApplicationContext:一種上下文,它從類路徑中載入上下文定義文件

  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中包含一個或多個元素

<?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定義包括:

  • classname:通常是bean的真正的實現類,但是如果一個bean使用一個靜態工廠方法所創建而不是被普通的構造函數創建,那么這就是工廠類的classname
  • bean行為配置元素:它聲明這個bean在容器中的行為方式,比如自動裝配模式、依賴檢查模式、初始化和析構方法
  • 構造函數的參數和新創建bean所需要的屬性:比如池的大小限制
  • 和這個bean工作相關的其他bean:比如它的合作者

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

  1、基於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方法來設置屬性。

  2、基於構造函數的依賴注入:它是通過調用帶有許多參數的構造方法來實現的,每個參數表示一個合作者或者屬性,下面就這種方法舉例

  使用這種方法,需要在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元素定義

  

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM