目標(biāo)明確
我們提供的服務(wù)有:成都網(wǎng)站制作、成都做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設(shè)、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、堯都ssl等。為1000多家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的堯都網(wǎng)站制作公司
簡單敘述一下本文想要解決的問題:如何在Spring中不再使用Spring創(chuàng)建Bean實例,而是把Bean創(chuàng)建過程轉(zhuǎn)移到開發(fā)者手中。
思路清晰
創(chuàng)建Bean實例的方式:
1) 通過構(gòu)造器(有參或無參)
方式:
2) 通過靜態(tài)工廠方法
方式:
注: 工廠類實例沒有創(chuàng)建
3) 通過實例工廠方法(非靜態(tài)方法)
方式:
注: 工廠類實例被創(chuàng)建
方法實用
示例1:
需求:
1 不想再bean.xml加載的時候?qū)嵗痓ean,而是想把加載bean.xml與實例化對象分離。
2 實現(xiàn)單例的bean
以上的情況,都可以通過工廠方法factory-method來創(chuàng)建bean。
這樣再加載bean.xml時,不會直接實例化bean,而是當(dāng)調(diào)用factory-method所指的方法時,才開始真正的實例化。
實現(xiàn):通過spring的factory-method來創(chuàng)建單例的bean
首先通過靜態(tài)內(nèi)部類創(chuàng)建一個單例對象
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"?>
通過應(yīng)用上下文調(diào)用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(); } }
執(zhí)行結(jié)果
一月 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 演出開始...
工廠方法創(chuàng)建bean介紹
1. 使用靜態(tài)工廠方法創(chuàng)建Bean
使用靜態(tài)工廠方法創(chuàng)建Bean實例時,class屬性也必須指定,但此時class屬性并不是指定Bean實例的實現(xiàn)類,而是靜態(tài)工廠類。因為Spring需要知道是用哪個工廠來創(chuàng)建Bean實例。另外,還需要使用factory-method來指定靜態(tài)工廠方法名,Spring將調(diào)用靜態(tài)工廠方法(可能包含一組參數(shù)),來返回一個Bean實例,一旦獲得了指定Bean實例,Spring后面的處理步驟與采用普通方法創(chuàng)建Bean實例則完全一樣。需要注意的是,當(dāng)使用靜態(tài)工廠方法來創(chuàng)建Bean時,這個factory-method必須要是靜態(tài)的。這段闡述聽上去有點暈,話不多說,上代碼:
先定義一個接口,靜態(tài)方法產(chǎn)生的將是該接口的實例:
public interface Animal { public void sayHello(); }
下面是接口的兩個實現(xiàn)類:
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的靜態(tài)方法,該方法將根據(jù)傳入的參數(shù)決定創(chuàng)建哪個對象。這是典型的靜態(tài)工廠設(shè)計模式。
public clas AnimalFactory { public static Animal getAnimal(String type){ if ("cat".equalsIgnoreCase(type)){ return new Cat(); } else { return new Dog(); } } }
如果需要指定Spring使用AnimalFactory來產(chǎn)生Animal對象,則可在Spring配置文件中作如下配置:
從上面的配置可以看出:cat和dog兩個Bean配置的class和factory-method完全相同,這是因為兩個實例都使用同一個靜態(tài)工廠類、同一個靜態(tài)工廠方法產(chǎn)生得到的。只是為這個靜態(tài)工廠方法指定的參數(shù)不同,使用
主程序獲取cat和dog兩個Bean實例的方法不變,同樣只需要調(diào)用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(); } }
輸出結(jié)果:
貓貓,喵~喵~
狗狗,旺~旺~
使用靜態(tài)工廠方法創(chuàng)建實例時必須提供工廠類和產(chǎn)生實例的靜態(tài)工廠方法。通過靜態(tài)工廠方法創(chuàng)建實例時需要對Spring配置文件做如下改變;
class屬性不在是Bean實例的實現(xiàn)類,而是生成Bean實例的靜態(tài)工廠類
使用factory-method指定生產(chǎn)Bean實例的靜態(tài)工廠方法
如果靜態(tài)工廠方法需要參數(shù),使用
當(dāng)我們指定Spring使用靜態(tài)工廠方法來創(chuàng)建Bean實例時,Spring將先解析配置文件,并根據(jù)配置文件指定的信息,通過反射調(diào)用靜態(tài)工廠類的靜態(tài)工廠方法,并將該靜態(tài)工廠方法的返回值作為Bean實例,在這個過程中,Spring不再負(fù)責(zé)創(chuàng)建Bean實例,Bean實例是由用戶提供的靜態(tài)工廠方法提供的。
2. 使用實例工廠方法創(chuàng)建Bean
實例工廠方法與靜態(tài)工廠方法只有一點不同:調(diào)用靜態(tài)工廠方法只需要使用工廠類即可,調(diào)用實例工廠方法則必須使用工廠實例。所以在Spring配置上也只有一點區(qū)別:配置靜態(tài)工廠方法指定靜態(tài)工廠類,配置實例工廠方法則指定工廠實例。同樣是上面的例子將AnimalFactory修改為:
public clas AnimalFactory { public Animal getAnimal(String type){ //這里僅僅是去掉了static關(guān)鍵字 if ("cat".equalsIgnoreCase(type)){ return new Cat(); } else { return new Dog(); } } }
Spring文件修改為:
測試類不用修改,輸出結(jié)果和上面相同。
很多情況下使用
配置工廠Bean的三種方式。
抽象接口:
public interface IMusicBox { public void play(); }
1、靜態(tài)工廠方法取得Bean實例
工廠類:
public class MusicBoxFactory { public static IMusicBox createMusicBox(){ return new IMusicBox(){ public void play(){ System.out.println("Play piano..."); } }; } }
配置文件:
測試類:
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..."); } }; } }
配置文件:
“factory-bean”屬性指定工廠Bean,”factory-method”屬性指定工廠方法來取得Bean實例。
測試類:
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-config.xml"); IMusicBox musicbox = (IMusicBox)ctx.getBean("musicBox"); musicbox.play(); }
3、工廠類實現(xiàn)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; } }
配置文件:
測試類:
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-config.xml"); //不加 & 返回工廠的“產(chǎn)品” IMusicBox musicbox = (IMusicBox)ctx.getBean("musicBox"); musicbox.play(); //加 & 返回工廠類實例 Object obj = ctx.getBean("&musicBox"); System.out.println(obj.getClass().getName()); }
實現(xiàn)FactoryBean接口的類不會被視為普通的Bean,Spring會自動檢測,調(diào)用getObject方法獲取Bean實例
總結(jié)
Spring工廠方法實例化bean實例的介紹就到這里,有什么不足之處,大家可以留言指出。感謝朋友們對本站的支持!