SpringFactory 方法建立(執行個體化)bean執行個體代碼,springbean

來源:互聯網
上載者:User

SpringFactory 方法建立(執行個體化)bean執行個體代碼,springbean

目標明確

簡單敘述一下本文想要解決的問題:如何在Spring中不再使用Spring建立Bean執行個體,而是把Bean建立過程轉移到開發人員手中。

思路清晰

建立Bean執行個體的方式:

1) 通過構造器(有參或無參)

方式: <bean id="" class=""/>

2) 通過靜態Factory 方法

方式: <bean id="" class="工廠類" factory-method="靜態Factory 方法"/>

注: 工廠類執行個體沒有建立

3) 通過執行個體Factory 方法(非靜態方法)

方式:

<bean id="factory" class="工廠類"/>

<bean id="" factory-bean="factory" factory-method="執行個體Factory 方法"/>

注: 工廠類執行個體被建立

方法實用

樣本1

需求:

1 不想再bean.xml載入的時候執行個體化bean,而是想把載入bean.xml與執行個體化對象分離。

2 實現單例的bean

以上的情況,都可以通過Factory 方法factory-method來建立bean。

這樣再載入bean.xml時,不會直接執行個體化bean,而是當調用factory-method所指的方法時,才開始真正的執行個體化。

實現:通過spring的factory-method來建立單例的bean
  首先通過靜態內部類建立一個單例對象

package com.spring.test.factorymethod;public class Stage {  public void perform(){    System.out.println("演出開始...");  }  private Stage(){      }  private static class StageSingletonHolder{    static Stage instance = new Stage();  }  public static Stage getInstance(){    return StageSingletonHolder.instance;  }}

在spring設定檔中指定載入的方法getInstance

<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns="http://www.springframework.org/schema/beans"  xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">   <bean id="theStage" class="com.spring.test.factorymethod.Stage"     factory-method="getInstance"></bean></beans>

通過應用上下文調用bean擷取執行個體

package com.spring.test.factorymethod;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class test {  public static void main(String[] args) {    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");    Stage stage = ((Stage)ctx.getBean("theStage"));//.getInstance();    stage.perform();  }}

執行結果

一月 24, 2015 6:38:18 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh資訊: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@512dbd1a: startup date [Sat Jan 24 18:38:18 CST 2015]; root of context hierarchy一月 24, 2015 6:38:19 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions資訊: Loading XML bean definitions from class path resource [bean.xml]一月 24, 2015 6:38:19 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons資訊: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2d1879ea: defining beans [duke,sonnet29,poeticDuke,theStage]; root of factory hierarchy演出開始...

Factory 方法建立bean介紹

1. 使用靜態Factory 方法建立Bean

使用靜態Factory 方法建立Bean執行個體時,class屬性也必須指定,但此時class屬性並不是指定Bean執行個體的實作類別,而是靜態工廠類。因為Spring需要知道是用哪個工廠來建立Bean執行個體。另外,還需要使用factory-method來指定靜態Factory 方法名,Spring將調用靜態Factory 方法(可能包含一組參數),來返回一個Bean執行個體,一旦獲得了指定Bean執行個體,Spring後面的處理步驟與採用普通方法建立Bean執行個體則完全一樣。需要注意的是,當使用靜態Factory 方法來建立Bean時,這個factory-method必須要是靜態。這段闡述聽上去有點暈,話不多說,上代碼:

先定義一個介面,靜態方法產生的將是該介面的執行個體:

public interface Animal {  public void sayHello();}

下面是介面的兩個實作類別:

public class Cat implements Animal {  private String msg;  //依賴注入時必須的setter方法  public void setMsg(String msg){    this.msg = msg;  }  @Override  public void sayHello(){    System.out.println(msg + ",喵~喵~");  }} public class Dog implements Animal {  private String msg;  //依賴注入時必須的setter方法  public void setMsg(String msg){    this.msg = msg;  }  @Override  public void sayHello(){    System.out.println(msg + ",旺~旺~");  }}

下面的AnimalFactory工廠中包含了一個getAnimal的靜態方法,該方法將根據傳入的參數決定建立哪個對象。這是典型的靜態工廠設計模式。

public clas AnimalFactory {  public static Animal getAnimal(String type){    if ("cat".equalsIgnoreCase(type)){      return new Cat();    } else {      return new Dog();    }  }}

如果需要指定Spring使用AnimalFactory來產生Animal對象,則可在Spring設定檔中作如下配置:

<!-- 配置AnimalFactory的getAnimal方法,使之產生Cat --><bean id="cat" class="com.abc.AnimalFactory" factory-method="getAnimal">  <!-- 配置靜態Factory 方法的參數,getAnimal方法將產生Cat類型的對象 -->  <constructor-arg value="cat" />  <!-- 通過setter注入的普通屬性 -->  <property name="msg" value="貓貓" /></bean><!-- 配置AnimalFactory的getAnimal方法,使之產生Dog --><bean id="dog" class="com.abc.AnimalFactory" factory-method="getAnimal">  <!-- 配置靜態Factory 方法的參數,getAnimal方法將產生Dog類型的對象 -->  <constructor-arg value="dog" />  <!-- 通過setter注入的普通屬性 -->  <property name="msg" value="狗狗" /></bean>

從上面的配置可以看出:cat和dog兩個Bean配置的class和factory-method完全相同,這是因為兩個執行個體都使用同一個靜態工廠類、同一個靜態Factory 方法產生得到的。只是為這個靜態Factory 方法指定的參數不同,使用<constructor-arg />元素來為靜態Factory 方法指定參數。

主程式擷取cat和dog兩個Bean執行個體的方法不變,同樣只需要調用Spring容器的getBean()即可:

public class Test {  public static void main(String args[]){    ApplicationContext context =         new ClassPathXmlApplicationContext("applicationContext.xml");    Animal a1 = context.getBean("cat", Animal.class);    a1.sayHello();    Animal a2 = context.getBean("dog", Animal.class);    a2.sayHello();  }}

輸出結果:

<code class="hljs">貓貓,喵~喵~狗狗,旺~旺~</code>

使用靜態Factory 方法建立執行個體時必須提供工廠類和產生執行個體的靜態Factory 方法。通過靜態Factory 方法建立執行個體時需要對Spring設定檔做如下改變;

class屬性不在是Bean執行個體的實作類別,而是產生Bean執行個體的靜態工廠類

使用factory-method指定生產Bean執行個體的靜態Factory 方法

如果靜態Factory 方法需要參數,使用<constructor-arg />元素為其配置

當我們指定Spring使用靜態Factory 方法來建立Bean執行個體時,Spring將先解析設定檔,並根據設定檔指定的資訊,通過反射調用靜態工廠類的靜態Factory 方法,並將該靜態Factory 方法的傳回值作為Bean執行個體,在這個過程中,Spring不再負責建立Bean執行個體,Bean執行個體是由使用者提供的靜態Factory 方法提供的。

2. 使用執行個體Factory 方法建立Bean

執行個體Factory 方法與靜態Factory 方法只有一點不同:調用靜態Factory 方法只需要使用工廠類即可,調用執行個體Factory 方法則必須使用工廠執行個體。所以在Spring配置上也只有一點區別:配置靜態Factory 方法指定靜態工廠類,配置執行個體Factory 方法則指定工廠執行個體。同樣是上面的例子將AnimalFactory修改為:

public clas AnimalFactory {  public Animal getAnimal(String type){ //這裡僅僅是去掉了static關鍵字    if ("cat".equalsIgnoreCase(type)){      return new Cat();    } else {      return new Dog();    }  }}

Spring檔案修改為:

<!-- 先配置工廠類 --><bean id="animalFactory" class="com.abc.AnimalFactory" /><!-- 這裡使用factory-bean指定執行個體工廠類對象 --><bean id="cat" factory-bean="animalFactory" factory-method="getAnimal">  <!-- 同樣指定factory-method的參數 -->  <constructor-arg value="cat" />  <property name="msg" value="貓貓" /></bean><bean id="dog" factory-bean="animalFactory" factory-method="getAnimal">  <constructor-arg value="dog" />  <property name="msg" value="狗狗" /></bean>

測試類別不用修改,輸出結果和上面相同。

很多情況下使用<bean id=”bean1” class=”…” />定義一個bean,這種定義方式Spring將會調用預設的無參數構造方法建立Bean執行個體。除此之外還可以使用工廠方式建立Bean執行個體,實現Bean建立與使用的分離,將Bean建立工作交由工廠來完成。

配置工廠Bean的三種方式。

抽象介面:

public interface IMusicBox {    public void play(); } 

1、靜態Factory 方法取得Bean執行個體

工廠類:

public class MusicBoxFactory {   public static IMusicBox createMusicBox(){   return new IMusicBox(){        public void play(){     System.out.println("Play piano...");      }   };   } } 

設定檔:

<bean id="musicBox" class="test.spring.MusicBoxFactory" factory-method="createMusicBox" /> 

測試類別:

public static void main(String[] args) {   ApplicationContext ctx =    new ClassPathXmlApplicationContext("bean-config.xml");   IMusicBox musicbox = (IMusicBox)ctx.getBean("musicBox");   musicbox.play(); } 

2、工廠執行個體的方法取得Bean執行個體

工廠類:

public class MusicBoxFactory {   public IMusicBox createMusicBox(){//沒有static修飾   return new IMusicBox(){        public void play(){     System.out.println("Play piano...");      }   };   } } 

設定檔:

<bean id="factoryBean" class="test.spring.MusicBoxFactory" /> <bean id="musicBox" factory-bean="factoryBean" factory-method="createMusicBox" /> 

“factory-bean”屬性指定工廠Bean,”factory-method”屬性指定Factory 方法來取得Bean執行個體。

測試類別:

public static void main(String[] args) {   ApplicationContext ctx =    new ClassPathXmlApplicationContext("bean-config.xml");   IMusicBox musicbox = (IMusicBox)ctx.getBean("musicBox");   musicbox.play(); } 

3、工廠類實現org.springframework.beans.factory.FacotryBean介面

工廠類:

import org.springframework.beans.factory.FactoryBean;  public class MusicBoxFactory2 implements FactoryBean {   public Object getObject() throws Exception {   return new IMusicBox(){     public void play(){        System.out.println("Play piano...");        }   };   }    public Class getObjectType() {   return IMusicBox.class;   }    public boolean isSingleton() {   return false;   } } 

設定檔:

<bean id="musicBox" class="test.spring.MusicBoxFactory2"/> 

測試類別:

public static void main(String[] args) {   ApplicationContext ctx =    new ClassPathXmlApplicationContext("bean-config.xml");   //不加 & 返回工廠的“產品”   IMusicBox musicbox = (IMusicBox)ctx.getBean("musicBox");   musicbox.play();   //加 & 返回工廠類執行個體   Object obj = ctx.getBean("&musicBox");    System.out.println(obj.getClass().getName());   } 

實現FactoryBean介面的類不會被視為普通的Bean,Spring會自動檢測,調用getObject方法擷取Bean執行個體

總結

SpringFactory 方法執行個體化bean執行個體的介紹就到這裡,有什麼不足之處,大家可以留言指出。感謝朋友們對本站的支援!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.