Spring 裝配Bean
spring 裝配bean
spring裝配bean的三種機制
- 在XML中進行顯示配置
- 在Java中進行顯示配置
- 隱式的bean發現機制和自動裝配
自動化裝配bean
Spring從兩個角度來實現自動化裝配
- 元件掃描:Spring會自動發現應用上下文中所建立的bean
- 自動裝配:Spring自動滿足bean之間的依賴
Spring中有4種類型的元件自動掃描註釋型別
- @Component – 指示自動掃描元件。
- @Repository – 表示在持久層DAO元件。
- @Service – 表示在業務層服務元件。
- @Controller – 表示在表示層控制器元件。
開啟自動元件掃描
1 xml顯式配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="com.yiibai.customer" /> </beans>
2 註解式配置
@Configuration
@ComponentScan
public calss CDPlayerConfig(){
}
CDPlayerConfig中並沒有顯式地宣告任何bean,只不過它是用來@ComponentScan註解,這個註解能夠在spring中棄用元件掃描
如果沒有其他配置的話,@ComponentScan預設會掃描域配置類相同的包
無論註解式配置或者xml顯示配置,我們都可以明確地設定掃描的基礎班
<!-- 使用Annotation自動註冊Bean,只掃描@Controller --> <!-- base-package 如果多個,用“,”分隔 --> <context:component-scan base-package="com.digitalpublishing.sage.dc.controller" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
@ComponentScan(basePackages={"controller","service"})
建立可被發現的bean
建立POJO 加上註解@Component
元件掃描預設是不啟用的,我們需要顯示配置一下Spring,從而命令他去需找導遊@Component註解的類
,併為其建立bean
通過為bean添加註解實現自動裝配
@Autowired註解不僅能夠用在構造器上,還能用在屬性的Setter方法上
在spring初始化之後,它會盡可能去滿足bean的依賴,不管是構造器,setter方法還是在其他的方法,spring都會嘗試滿足方法引數上所宣告的依賴
假如有且只有一個bean匹配依賴需求的話,那麼這個bean將會被裝配進來
如果沒有匹配的bean,那麼在應用上下文建立的時候,spring會丟擲一個以上,為了避免異常的出現,你可以將@Autoeired的required屬性設定為false
但如果將required屬性設定為false時,spring會嘗試執行自動裝配,但是如果沒有匹配的bean的話,spring將會讓這個bean處於未裝配的狀態.如果在你的程式碼中沒有進行null檢查的話,這個處於未裝配狀態的屬性可能會導致空指標異常
儘管很多場景下通過元件掃描和自動裝配實現spring的自動化配置是更為推薦的方式,但如果你想要將第三方庫中的元件裝配到你的應用總,在這種情況下,是沒有辦法在它的類上新增@Component和@Autowired註解的,因此就不能使用自動化裝配的方案了
這種情況下,你必須要採用顯式裝配的方式,在顯式配置的時候,有兩種可選方案
- java
- xml
通過Java程式碼裝配bean
進行顯式配置是,JavaConfig是更好的方案,它更強大,型別安全並且對重構友好
因為它就是Java程式碼,就像應用程式中的其他Java程式碼一樣
但JavaConfig與其他的Java程式碼又有所區別,JavaConfig是配置大媽,這意味著它不應該包含任何業務邏輯,JavaConfig也不應侵入到業務邏輯程式碼中,其應放到單獨的保重,使它與其他的應用程式邏輯分離開來
建立配置類
建立配置類,為其新增@Configuration註解,@Configuration註解表明這個類是一個配置類,該類應該包含在spring應用上下文中如何建立bean的細節
宣告簡單的bean
要在JavaConfig中宣告bean,我們需要編寫一個方法,這個方法會建立所需型別的例項,然後給這個方法新增@Bean註解
@Bean註解會告訴spring這個方法將會返回一個物件,該物件要註冊為spring應用上下文中的bean,方法體中包含了最終產生bean例項的邏輯
@Configuration
public class CDPlayerConfig{
@Bean
public CompactDisc sgtPeppers(){
return new SgtPeppers();
}
}
藉助JavaConfig實現注入
@Configuration
public class CDPlayerConfig{
@Bean
public CompactDisc sgtPeppers(){
return new SgtPeppers();
}
@Bean
public CDPlayer cDPlayer(){
return new CDPlayer()(sgtPeppers());
}
}
cDPlayer()方法像sgtPeppers()方法一樣,同樣使用了@Bean註解,這表明這個方法會建立一個bean例項並將其註冊到spring應用上下文中,所建立的beanID為cdPlayer,與方法的名字相同
cDPlayer()的方法體與sgtPeppers()稍微有些區別,在這裡並沒有使用預設的構造器構建例項,而是呼叫了需要傳入CompactDisc物件的構建器來建立CDPlayer例項
看起來,CompactDisc是榮國呼叫sgtPeppers()得到的,但情況並非如此,因為sgtPeppers()方法上添加了@Bean註解,spring將會攔截所有對他的呼叫,並確保直接返回該方法所建立的bean,而不是每次都對其進行實際的呼叫
通過xml裝配bean
建立xml配置規範
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context">
</beans>
宣告一個簡單的
<bean id="demoController" class="soundsystem.CDPlayer" />
這裡聲明瞭一個很簡單的bean,建立這個bean的類通過class屬性來指定的,並且要使用全限定的類名
藉助構造器注入初始化的bean
在springxml配置中,只有一種宣告bean的方式:使用
xml宣告DI時,具體到構造器注入,有樑總節本配置方案選擇
- 使用spring3.0所引入的c-名稱空間
<bean id="cdPlayer" class="soundsystem.CDPlayer"
<constructor-arg ref="copactDisc" />
</bean>
當spring遇到這個
c-名稱空間
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cdPlayer" class="soundsystem.CDPlayer"
c:cd-ref="compactDisc" />
</beans>
也可以直接注入值
將字面量注入到構造器中
我們不止可以將物件的引用裝配到依賴於它們的其他物件之中,而且可以用一個字面量值來配置物件
例如:
//POJO
public class BlankDisc {
private String title;
private String artist;
public BlankDisc(String title,String artist){
this.title = title;
this.artist = artist;
}
public void play(){
System.out.println("playing" + title + "by" ++ artist);
}
}
<bean id="cdPlayer" class="soundsystem.CDPlayer" >
<constructor-arg value="sgt.Pepper's lonely hearts clue band" />
<constructor-arg value="The Beatles" />
</bean>
使用value屬性,通過該屬性表明給定的值要以字面量的形式注入到構造器中
c-名稱空間
第一種,引用構造器引數的名字
<bean id="demoController" class="soundsystem.CDPlayer" >
<c:_title="sgt.Pepper's lonely hearts clue band" />
<c:_artist=="The Beatles" />
</bean>
第二中,通過引數索引裝配相同的字面量值
<bean id="demoController" class="soundsystem.CDPlayer" >
<c:_0="sgt.Pepper's lonely hearts clue band" />
<c:_1=="The Beatles" />
</bean>
xml不允許摸個元素的多個屬性具有相同的名字,因此,如果有兩個或更多的構造器引數的話,我們不能簡單地使用下劃線進行標識.但是如果只有一個構造引數的話,就可以
裝配集合 c-名稱空間無法作答
//POJO
public class BlankDisc {
private String title;
private String artist;
private List<String> tracks;
public BlankDisc(String title,String artist){
this.title = title;
this.artist = artist;
this.tracks = tracks;
}
public void play(){
System.out.println("playing" + title + "by" ++ artist);
}
}
<bean id="cdPlayer" class="soundsystem.CDPlayer" >
<constructor-arg value="sgt.Pepper's lonely hearts clue band" />
<constructor-arg value="The Beatles" />
<constructor-arg><null/></constructor-arg>
</bean>
因為增加了一個tarcts屬性,在宣告bean的時候 我們必須給出宣告,最簡單的方法就是將列表設定為null,因為它是要給構造器引數,我們必須給出宣告,所以採用上述方式傳遞null給他
但更好的解決辦法是提供一個列表
例如:
<bean id="cdPlayer" class="soundsystem.CDPlayer" >
<constructor-arg value="sgt.Pepper's lonely hearts clue band" />
<constructor-arg value="The Beatles" />
<constructor-arg>
<list>
<value>sgt.Pepper's lonely hearts clue band</value>
<value>A</value>
<value>B</value>
</list>
</constructor-arg>
</bean>
也可以用
<bean id="cdPlayer" class="soundsystem.CDPlayer" >
<constructor-arg value="sgt.Pepper's lonely hearts clue band" />
<constructor-arg value="The Beatles" />
<constructor-arg>
<list>
<ref bean="sagtPepers"/>
<ref bean="A"/>
<ref bean="B"/>
</list>
</constructor-arg>
</bean>
設定屬性 (setter注入)
<bean id="cdPlayer" class="soundsystem.CDPlayer" >
<property name="compactDisc" ref="compactDisc" />
</bean>
//<property>元素為屬性的setter方法提供的功能,與<constructor-arg>元素為構造器所提供的功能一樣
//在本例中,它引用了ID為compactDisc的bean(通過ref屬性),並將期注入到compactDisc屬性中(通過setCompactDisc()方法).