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的屬性注入集合。