1. 程式人生 > >Spring裝配bean的3種方式

Spring裝配bean的3種方式

記錄自己學習Spring的歷程,參考書:spring in action

首先自建一個SpringMVC專案;自建專案過程中遇到兩個eclipse的問題:

1.    建立maven專案,但是沒有webContent檔案

        右鍵專案-》Properties-》Project Facets-》Dynamic Web Module

2.    WebContent檔案下沒有web.xml

        右鍵專案-》Java EE Tools-》Generate Deployment Descriptor Stub

我的maven依賴配置:

 <dependencies>
  	<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.1.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.1.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    	<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>4.1.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
	<dependency>
    	<groupId>junit</groupId>
    	<artifactId>junit</artifactId>
    	<version>4.12</version>
    	<scope>test</scope>
	</dependency>
  </dependencies>

Spring裝配Bean有3中方式:

    1.自動化配置

    2.JavaConfig

    3.XML

自動化配置:

1.在java中配置自動掃描,預設掃面當前包以及當前包下的所有子包

@Configuration
@ComponentScan
public class CDPlayerConfig {

}

    指定掃描的基礎包

@ComponentScan("com.spring")

    還可以表明設定的基礎包

@ComponentScan(basePackages={"com.spring","com.jpa"})

    以上都是通過String指定基礎包,這種方法有可能是不安全的(沒有理解),如果重構程式碼的話,所有指定的基礎包有可能出現錯誤,所以可以這樣(這些類所在的包將會作為掃描的基礎包):

@Component(basePackageClasses={My.class,She.class})

2.在XML中配置自動掃描

 <!-- 開啟註解自動掃描 -->
    <context:component-scan base-package="com.lcf.spring"/>

在當前情況下,所有存在@Component註解的類,都會被自動掃描為bean,如果沒有指定bean的id,那麼bean的id將會以類名首字母小寫的方式存在。

@Component
public class SqtPeppers implements CompactDisc {
}

指定bean的id:

@Component("sqt")

自動裝配就是讓Spring自動滿足bean依賴的方法,藉助@Autowired註解。

可以用在構造器上:

	@Autowired
	public CDPlayer(SqtPeppers sqt){
		this.sqt = sqt;
	}

可以用在setter方法上:

	@Autowired
	public void setSqtPeppers(SqtPeppers sqt){
		this.sqt = sqt;
	}

可以用在屬性上:

	@Autowired
	private SqtPeppers sqt;

以上都可以實現自動裝配,但是如果沒有匹配的bean裝配,那麼在應用上下文建立時,Spring丟擲異常。為了避免異常:

@Autowired(required=false)

如果沒有匹配成功,將會讓該bean處於未匹配狀態。

通過java程式碼裝配bean

@Configuration
//@ComponentScan
public class CDPlayerConfig {
	@Bean(name="sqt")
	public CompactDisc sqtPeppers(){
		return new SqtPeppers();
	}
	@Bean
	public MediaPlay cdPlay(){
		return new CDPlayer(new SqtPeppers());
	}
}

javaConfig中去出了@ComponentScan註解,轉而使用方法配合@Bean註解的方式獲取bean;預設是bean的id就是方法名,因為sqtPeppers()方法上有@Bean註解,所以在cdPlay()方法中呼叫的new物件會被Spring攔截,直接返回相應的bean。

其實可以這麼寫(一樣的):

	@Bean
	public MediaPlay cdPlay(CompactDisc compactDisc){
		return new CDPlayer(compactDisc);
	}

通過XML配置bean

        宣告一個簡單的bean:     

    <bean class="com.lcf.spring.fitoutBean.SqtPeppers"/>

由於沒有給定Id,所以這裡使用了全限定類名指定ID,此時bean的ID為“com.spring.CDPlayer#0,其中#0是一個計數形式,用於區分相同型別的不同bean。

指定id:

<bean id="sqt" class="com.lcf.spring.fitoutBean.SqtPeppers"/>

        藉助構造器注入初始化bean:

        1.    <constructor-arg>元素

 <bean class="com.lcf.spring.fitoutBean.CDPlayer" >
	<constructor-arg ref="sqt"/></bean>

        2.    使用Spring3.0引入的c-名稱空間:

                需要在XML的頂部宣告其模式

 xmlns:c="http:www.springframework.org/schema/c"

                在c-名稱空間聲明後,可以使用來宣告構造引數

   <bean class="com.lcf.spring.fitoutBean.CDPlay"
    	c:sqt-ref="sqt"
    />

        上述使用構造引數時,直接引用了構造引數的名稱“sqt”,還支援位置引用的方式

   <bean class="com.lcf.spring.fitoutBean.CDPlay"
    	c:_0-ref="sqt"
    />

        XML中不允許數字作為第一個字元,所以使用了下劃線。

        當只有一個構造引數時,我們也可以簡寫:

   <bean class="com.lcf.spring.fitoutBean.CDPlay"
    	c:_-ref="sqt"
    />

        迄今為止,做到的都是引用注入,接下來注入字面量(value):

   <bean id="blank" class="com.lcf.spring.fitoutBean.BlankDisc">
    	<constructor-arg value="Sgt. Pepper`s Lonely hearts Club band"/>
    	<constructor-arg value="The Beatles"/>
    </bean>

        也可以使用c-名稱空間:

    <bean class="com.lcf.spring.fitoutBean.BlankDisc"
    	c:_title=""
    	c:_artist=""
    />
    <bean class="com.lcf.spring.fitoutBean.BlankDisc"
    	c:_0=""
    	c:_1=""
    />

        當只有一個引數時,也可以簡寫:

    <bean class="com.lcf.spring.fitoutBean.BlankDisc"
    	c:_=""
    />

        引用和字面量的裝配,對於c-名稱空間或者<constructor-arg>是沒有區別的,但是一下的裝配是c-名稱空間做不到的。

        裝配集合:

  <bean id="blank" class="com.lcf.spring.fitoutBean.BlankDisc">
    	<constructor-arg value="Sgt. Pepper`s Lonely hearts Club band"/>
    	<constructor-arg value="The Beatles"/>
    	<constructor-arg>
    		<list>
    			<value></value>
    			<value></value>
    			<value></value>
    		</list>
    	</constructor-arg>
    </bean>

        我們也可以使用ref代替value代表引用,使用Set時替換<list>為<set>,<set>會忽略重複的元素,並且不能保證順序,學習Spring in action時,是無法使用c-名稱空間宣告集合的。

        以上完全是通過構造器注入,接下來使用setter注入的方式:

     <bean class="com.lcf.spring.fitoutBean.CDPlayer" >
    <property name="sqtPeppers" ref="sqt"></property>
    </bean>

        強依賴使用構造器注入,可選性依賴使用setter注入。

        使用p-名稱空間,與c-名稱空間的用法類似,p-名稱空間為了簡寫<property>標籤。

        宣告p-名稱空間:

xmlns:p="http:www.springframework.org/schema/c"

        使用p-名稱空間進行setter注入:

    <bean class="com.lcf.spring.fitoutBean.CDPlayer"
    	p:sqt-ref="sqt"
    />

        注入字面量時,與構造器注入類似,將<contructor-arg>替換為<property>即可。

        p-名稱空間也無法裝配集合。

        使用util-名稱空間:

        首先宣告util:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:c="http://www.springframework.org/schema/c" xmlns:p="http://www.springframework.org/schema/c" xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util.xsd">

        使用util-名稱空間可以宣告list、set元素:

    <util:list id="trackList">
    	<vlaue></vlaue>
    	<vlaue></vlaue>
    	<vlaue></vlaue>
    </util:list>
        bean的屬性注入集合。