閱讀794 返回首頁    go 阿裏雲 go 技術社區[雲棲]


《Spring攻略(第2版)》——1.7 使用Spring的FactoryBean創建Bean

本節書摘來自異步社區《Spring攻略(第2版)》一書中的第1章,第1.7節,作者: 【美】Gary Mak , Josh Long , Daniel Rubio著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看

1.7 使用Spring的FactoryBean創建Bean

1.7.1 問題
你可能希望用Spring的工廠Bean在Spring IoC容器中創建Bean。工廠Bean(Factory bean)是作為創建IoC容器中其他Bean的工廠的一個Bean。概念上,工廠Bean與工廠方法非常類似,但是它是Bean構造期間可被Spring IoC容器識別的Spring專用Bean。

1.7.2 解決方案
工廠Bean的基本要求是實現FactoryBean接口。為了方便,Spring提供了抽象模板類AbstractFactoryBean供你擴展。

工廠Bean主要用於實現框架機製。下麵是一些例子:

在JNDI中查找對象(例如一個數據源)時,你可以使用JndiObjectFactoryBean。
使用經典Spring AOP為一個Bean創建代理時,可以使用ProxyFactoryBean。
在IoC容器中創建一個Hibernate會話工廠時,可以使用LocalSessionFactoryBean。
但是,作為框架用戶,你難得有必要編寫自定義的工廠Bean,因為它們是框架專用的,無法用在Spring IoC容器之外。實際上,你總是能夠為工廠Bean實現一個等價的工廠方法。

1.7.3 工作原理
盡管你很少有必要編寫自定義的工廠Bean,但是會發現通過一個實例來理解其內部機製很有幫助。例如,你可以為創建一個適用價格折扣的產品編寫一個工廠Bean。它接受一個product屬性和一個discount屬性,將折扣應用到產品上並且作為一個新的Bean返回。

package com.apress.springrecipes.shop;

import org.springframework.beans.factory.config.AbstractFactoryBean;

public class DiscountFactoryBean extends AbstractFactoryBean {

   private Product product;
   private double discount;

   public void setProduct(Product product) {
     this.product = product;
   }

   public void setDiscount(double discount) {
     this.discount = discount;
   }

   public Class getObjectType() {
     return product.getClass();
   }

   protected Object createInstance() throws Exception {
     product.setPrice(product.getPrice() * (1 - discount));
     return product;
   }
}

通過擴展AbstractFactoryBean類,你的工廠Bean能夠重載createInstance()方法以創建目標Bean實例。此外,你必須在getObjectType()方法中返回目標Bean的類型,使自動裝配(Auto-wiring)功能正常工作。

接下來,你可以用DiscountFactoryBean聲明你的產品實例。每當你請求一個實現Factory Bean接口的Bean,Spring IoC容器將使用這個工廠Bean創建目標Bean並且返回給你。如果你確定希望得到工廠Bean的實例,可以在Bean名稱之前加上&。

<beans ...>
   <bean 
     >
     <property name="product">
        <bean >
          <constructor-arg value="AAA" />
          <constructor-arg value="2.5" />
        </bean>
     </property>
     <property name="discount" value="0.2" />
   </bean>

   <bean 
     >
     <property name="product">
        <bean >
          <constructor-arg value="CD-RW" />
          <constructor-arg value="1.5" />
        </bean>
     </property>
     <property name="discount" value="0.1" />
   </bean>
</beans>

前述的工廠Bean配置的工作方式和下麵的代碼片段類似:

DiscountFactoryBean aaa = new DiscountFactoryBean();
aaa.setProduct(new Battery("AAA", 2.5));
aaa.setDiscount(0.2);
Product aaa = (Product) aaa.createInstance();

DiscountFactoryBean cdrw = new DiscountFactoryBean();
cdrw.setProduct(new Disc("CD-RW", 1.5));
cdrw.setDiscount(0.1);
Product cdrw = (Product) cdrw.createInstance();

最後更新:2017-05-31 15:31:26

  上一篇:go  《Spring攻略(第2版)》——1.8 使用工廠Bean和Utility Schema定義集合
  下一篇:go  《Spring攻略(第2版)》——1.6 為集合元素指定數據類型