Spring之建立Bean的方式
阿新 • • 發佈:2019-01-05
Bean有別於傳統的JavaBean,任何應用元件都可以作為Bean,接下來講述的是Spring中建立Bean的方式。
1.呼叫構造器建立Bean
使用構造器來建立Bean是最常見的情況,如果是構造注入,則通過配置建構函式來實現建立Bean,如果是設值注入,Spring底層會呼叫Bean類的無引數構造器來建立例項。以下講述的是設值注入。 以下是需要的介面package impl;
public interface Axe {
public String chop();
}
package impl; public interface Creature { public void useTool(); }
package impl;
public interface Metal {
public String make();
}
以下是三個介面相應的實現類:package impl.handle;
import impl.Axe;
public class StealAxe implements Axe {
@Override
public String chop() {
// TODO Auto-generated method stub
return "使用斧頭砍柴";
}
}
package impl.handle; import impl.Axe; import impl.Creature; import impl.Metal; public class Person implements Creature { private Axe axe; private Metal metal; // 設值注入所需的setter方法 public void setMetal(Metal metal) { this.metal=metal; } public void setAxe(Axe axe) { this.axe=axe; } public void useTool() { System.out.println("我打算去砍點柴火!"); // 呼叫axe的chop()方法, // 表明Person物件依賴於axe物件 System.out.println(metal.make()); System.out.println(axe.chop()); } }
package impl.handle;
import impl.Metal;
public class Steal implements Metal {
public String make()
{
return "使用鐵做斧頭";
}
}
根據需要的功能,編寫工具類
然後對Beans.xml檔案進行配置package test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import impl.handle.*; import impl.* ;public class BeanTest { public static void main(String[] args)throws Exception { // 以類載入路徑下的beans.xml檔案建立Spring容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // ① // 載入類的時候需要載入介面,從而真正實現面向介面程式設計。 Creature c=(Creature)ctx.getBean("person", Creature.class); c.useTool(); } }
<?xml version="1.0" encoding="GBK"?>
<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-4.0.xsd">
<!-- 配置名為person的Bean,其實現類是org.crazyit.app.service.Person類 -->
<bean id="person" class="impl.handle.Person">
<property name="metal" ref="steal"/>
<property name="axe" ref="stealAxe"/>
</bean>
<bean id="steal" class="impl.handle.Steal"/>
<bean id="stealAxe" class="impl.handle.StealAxe"/>
</beans>
以上是設值注入,所以使用的是Spring底層呼叫Bean類的無引數構造器來建立例項的。這裡的Bean類是指Steal類和StealAxe類。
2.呼叫靜態工廠方法建立Bean
所謂靜態工廠方法就是建立一個工廠類,工廠類有個靜態工廠方法,讓產品的例項化在工廠類的靜態工廠方法中進行,讓整個過程都面向介面程式設計。並且在配置beans.xml檔案略有不同。通過以下例子進行詳細講述。 首先先定義一個介面,該介面的例項就是在靜態工廠方法中生產的。package handle;
public interface Being {
public void testBeing();
}
以下兩個類Dog類和Cat類便是以上介面的實現類。
package handle.impl;
import handle.Being;
public class Dog implements Being {
private String msg;
public void setMsg(String msg)
{
this.msg=msg;
}
//實現介面中的testBeing()方法
@Override
public void testBeing() {
// TODO Auto-generated method stub
System.out.println(msg+",狗愛啃骨頭");
}
}
package handle.impl;
import handle.Being;
public class Cat implements Being {
private String msg;
public void setMsg(String msg)
{
this.msg=msg;
}
@Override
public void testBeing() {
// TODO Auto-generated method stub
System.out.println(msg+",貓喜歡吃老鼠");
}
}
相應的類都準備就緒,產品的原料都到了,就等著工廠進行集中生產,於是我們應當建立一個工廠類,然後在工廠類中建立一個靜態工廠方法,將所有的類進行相應的例項化。
package factory;
import handle.*;
import handle.impl.*;
public class BeingFactory {
//返回Being例項的靜態工廠方法
public static Being getBeing(String arg)
{
//呼叫次靜態方法的引數是dog,則返回Dog例項
if(arg.equalsIgnoreCase("dog"))
{
return new Dog();
}
else
{
return new Cat();
}
}
}
以上便是一個工廠類BeingFactory,而工廠類有個靜態方法是getBeing(String arg),而arg是傳入的引數,相當於外界需要什麼類的例項,則工廠方法就例項化什麼類。
以下是beans.xml的配置內容:
<?xml version="1.0" encoding="GBK"?>
<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-4.0.xsd">
<bean id="dog" class="factory.BeingFactory" factory-method="getBeing">
<constructor-arg value="dog"/>
<property name="msg" value="我是狗"/>
</bean>
<bean id="cat" class="factory.BeingFactory" factory-method="getBeing">
<constructor-arg value="cat"/>
<property name="msg" value="我是貓"/>
</bean>
</beans>
可以看出<bean.../>子元素中id還是指例項名,作為標識作用,而class與構造器建立Bean的有所不同,構造器建立Bean的class指的是id對應的需要例項的類名,而靜態工廠方法建立Bean中的class是工廠類的類名(包含包路徑),另外不同的是還多了factory-method元素,是指工廠類中的靜態工廠方法名,如上便是getBeing。而靜態方法需要的相應的引數,則使用<constructor-arg.../>傳入,而傳入的引數還需要引數,則由<property.../>元素傳入。
接下來是建立工具類:
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import handle.*;
public class SpringTest {
public static void main(String[] args)
{
// 以類載入路徑下的beans.xml檔案建立Spring容器
ApplicationContext ctx = new
ClassPathXmlApplicationContext("beans.xml");
Being b1=ctx.getBean("dog", Being.class);
b1.testBeing();
Being b2=ctx.getBean("cat", Being.class);
b2.testBeing();
}
}
執行工具類之後,得到如下結果:
我是狗,狗愛啃骨頭
我是貓,貓喜歡吃老鼠
以上便是靜態工廠方法建立Bean的示例。與構造器建立Bean最大的不同便是使用了工廠方法集中例項化,還有就是配置中<bean.../>元素中的class的不同。
3.呼叫例項工廠方法建立Bean
呼叫例項工廠方法與呼叫靜態工廠方法類似,只是工廠類中的工廠方法有無static之分,以及配置上內容稍有差異,為便於區分,仍然使用呼叫靜態工廠方法的示例。先是產品介面:
package handle;
public interface Being {
public void testBeing();
}
然後相應的產品類:
package handle.impl;
import handle.Being;
public class Dog implements Being {
private String msg;
public void setMsg(String msg)
{
this.msg=msg;
}
//實現介面中的testBeing()方法
@Override
public void testBeing() {
// TODO Auto-generated method stub
System.out.println(msg+",狗愛啃骨頭");
}
}
package handle.impl;
import handle.Being;
public class Cat implements Being {
private String msg;
public void setMsg(String msg)
{
this.msg=msg;
}
@Override
public void testBeing() {
// TODO Auto-generated method stub
System.out.println(msg+",貓喜歡吃老鼠");
}
}
建立工廠類,可以看到工廠類中的工廠方法沒有static。
package factory;
import handle.*;
import handle.impl.*;
public class BeingFactory {
//返回Being例項的靜態工廠方法
public Being getBeing(String arg)
{
//呼叫次靜態方法的引數是dog,則返回Dog例項
if(arg.equalsIgnoreCase("dog"))
{
return new Dog();
}
else
{
return new Cat();
}
}
}
以下是beans.xml的配置:
<?xml version="1.0" encoding="GBK"?>
<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-4.0.xsd">
<!-- 配置名為beingFactory的工廠類Bean,其實現類是factory.beingFactory類 -->
<bean id="beingFactory" class="factory.BeingFactory"/>
<!-- 下面配置驅動Spring呼叫beingFactory Bean的getBeing()方法來建立Bean,該Bean元素包含地constructor-arg元素用於為工廠方法指定引數
BeingFactory bf=container.get("beingFactory");//container代表Spring容器
dog=bf.getBeing("dog");-->
<bean id="dog" factory-bean="beingFactory" factory-method="getBeing">
<constructor-arg value="dog"/>
<property name="msg" value="我是狗"/>
</bean>
<bean id="cat" factory-bean="beingFactory" factory-method="getBeing">
<constructor-arg value="cat"/>
<property name="msg" value="我是貓"/>
</bean>
</beans>
從以上配置內容可以看出,先對工廠類進行配置,工廠類的配置跟呼叫構造器的配置類似,主要是id與class,然後進行配置產品例項,id仍然是產品名,但是沒有class,而是用factory-bean取代,factory-bean就是前面已經配置好的工廠類的id,factory-method則是工廠方法,其餘都同調用靜態工廠方法。主要區別在於先進行工廠類的Bean配置,然後配置產品Bean例項時,class用factory-bean取代。
最後建立工具類:
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import handle.*;
public class SpringTest {
public static void main(String[] args)
{
// 以類載入路徑下的beans.xml檔案建立Spring容器
ApplicationContext ctx = new
ClassPathXmlApplicationContext("beans.xml");
Being b1=ctx.getBean("dog", Being.class);
b1.testBeing();
Being b2=ctx.getBean("cat", Being.class);
b2.testBeing();
}
}
執行工具類,得到如下結果:
我是狗,狗愛啃骨頭
我是貓,貓喜歡吃老鼠
綜上所述,建立Bean的三種方式,首先使用工廠方法建立Bean與呼叫構造器建立Bean的區別在於:1.前者使用了工廠方法便於集中管理,而後者只是將Bean例項作為引數傳入其它類。2.配置beans.xml的內容略有不同。
而呼叫靜態方法建立Bean與呼叫例項工廠方法建立Bean的區別:
1.配置例項工廠方法建立Bean,必須將例項工廠配置成Bean例項,而配置靜態工廠方法建立Bean,無須配置工廠Bean
2.配置例項工廠方法建立Bean,必須使用factory-bean屬性確定工廠Bean,而配置靜態工廠方法建立Bean,使用class元素確定靜態工廠類。
相同之處:
1.都需要factory-method屬性確定Bean例項的工廠方法
2.工廠方法需要引數,都使用<constructor-arg.../>元素指定引數值
3.普通的設值注入,都使用<property.../>元素確定引數值