02 裝配Bean
2.1 Spring配置的可選方案
在XML中顯式配置
在Java中進行顯式配置
隱式的bean發現機制和自動裝配機制
建議是,盡可能使用隱式的配置,在必須使用顯式配置時(比如你沒有源代碼),最好采用JavaConfig而不是XML
只有想要使用便利的XML命名空間並且在JavaConfig沒有同樣的實現時,才應該使用XML
JavaConfig相對於XML的直接優勢是重構友好,並且構造bean時可以通過Java代碼精細控制
2.2 自動化裝配Bean
Spring從兩個角度實現自動化裝配
組件掃描:Spring會自動發現應用上下文中所創建的Bean
自動裝配:Spring自動滿足bean之間的依賴
@Component用於告知Spring這是一個Bean,需要實例化,具有同樣功能的還有@Repository、@Service和@Controller
可使用@ComponentScan註解開啟組件掃描,此時Spring會掃描配置類所在的包以及它們的子包
若想更改掃描的包,可以使用value屬性(只能指定一個)或者basePackages屬性(是一個數組,可以指定多個)指定要掃描的基本包
此外,還可以使用basePackageClasses,該屬性是一個Class數組,可以提供多個Class,Spring會以這些Class所在的包作為基本包
可以在需要掃描的包中創建一個空標記接口,並將basePackages設置為這個接口,這樣可以保持對重構的友好引用
如果使用XML配置,也可以使用 <context:component-scan base-package=""/>起用組件掃描
Spring能很方便地進行單元測試:
1.創建一個普通類,添加@RunWith(SpringJunit4ClassRunner.class)註解
2.使用@contextConfiguration()提供配置信息,XML使用location屬性,JavaConfig使用class屬性
3.在測試類內部可以使用@Autowired等註解進行自動裝配,之後即可進行單元測試
可以使用@Component註解的value屬性為定義的bean命名,也可是使用基於JDI規範所定義的@Name註解來為bean定義名稱
可以使用@Autowired註解進行Bean的自動裝配,該註解一般用在構造器,屬性的set方法上
其實@Autowired能用在類的任何方法上,Spring都會嘗試滿足方法參數上所聲明的依賴,如果只有一個Bean滿足條件,那麽這個Bean會被裝配進來
如果沒有匹配的bean,那麽應用上下文創建的時候會拋出異常
為了避免異常,可以設置@Autowired的required屬性為false,表示允許為空,但此時運行時可能出現空指針異常
如果有多個bean滿足依賴關系,Spring也會拋出一個異常,表明沒有明確指定bean進行自動裝配
可以使用基於JDI的@Inject實現和@Autowired相同的功能
2.3 通過Java代碼裝配Bean
在進行顯式配置時,JavaConfig是更好的方案,它更加強大、類型安全並且對重構友好
JavaConfig不應該包含任何業務邏輯,也不應該侵入到業務邏輯代碼之中
一般將JavaConfig置於單獨的包中,使它與其他的應用程序邏輯分離開來
相關註解有:@Configuration、@ComponentScan、@Bean、@Scope
註意最好不要自己new進行註入,因為@Bean註解方法所產生的bean默認為單例的,若需要多例的bean,可以利用@scope註解更改
可以使用調用方法進行註入,這要求被註入的bean的方法在同一個JavaConfig中:
@Bean
public Person person(){
return new Person(head());
}
利用方法參數進行註入,可用性強,事實上可以是任何方式產生的bean都可以被註入進來(包括XML的註解掃描的bean,而且可按名稱或類型,只要沒有歧義即可):
@Bean
public Person person(Head head){
return new Person(head);
}
2.4 通過XML裝配Bean
使用<bean>標簽聲明一個簡單的bean
<bean id="minstrel" class="com.hao.ioc.Minstrel">
使用<constructor-arg>標簽進行構造器註入,可以利用c命名空間精簡配置
<bean id="cdPlayer" class="sound.CDPlayer">
<constructor-arg ref="compactDisc"/>
</bean>
<bean id="cdPlayer" class="sound.CDPlayer" c:cd-red="compactDisc"/>
<bean id="cdPlayer" class="sound.CDPlayer" c:_0-red="compactDisc"/>
<bean id="cdPlayer" class="sound.CDPlayer" c:_-red="compactDisc"/>
還可以將字面值通過構造器註入
<bean id="compactDisc" class="sound.BlankDisk">
<constructor-arg value="..."/>
<constructor-arg value="..."/>
</bean>
<bean id="compactDisc" class="sound.BlankDisk" c:_title="..." c:_artist="..."/>
<bean id="compactDisc" class="sound.BlankDisk" c:_0="..." c:_1="..."/>
裝配集合(c命名空間無法做到的)
可以使用<null/>表示null
使用<list>標簽表示集合,可用於集合的裝配,<set>的用法和<list>同理
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
<list>
<ref bean="1"/>
<ref bean="2"/>
<ref bean="3"/>
</list>
通用的規則:對強依賴使用構造器註入,可選性的依賴使用屬性註入
使用<property>標簽設置屬性或者利用p命名空間
基於util命名空間的<util:list>可以用於構造列表Bean
2.5 導入和混合配置
1.在JavaConfig中引入配置
可使用@Import註解引入其他JavaConfig類的配置
可使用@ImportResource註解引入其他XML配置
可以創建一個更高層的配置類,在這個類上引入其他所需要的JavaConfig類
2.在XML中引入配置
可以使用<import>標簽引入其他XML配置
<import resource="classpath:app.xml"/>
可以使用bean標簽引入JavaConfig配置
甚至可以使用<context:component-scan>掃描JavaConfig類所在的包,引入這些JavaConfig類的配置
3.常規做法
通常會使用一個跟配置,然後這個配置會將更多的裝配類或JavaConfig組合起來
比如,在XML中定義掃描配置類所在的包,然後由配置類進行Bean的配置
2.6 小結
Spring框架的核心是Spring容器
容器負責管理應用程序中組件的生命周期,他會創建組件並保證他們的依賴能夠得到滿足
Spring裝配Bean的三種主要方式:自動化裝配、基於JavaConfig的顯式配置以及基於XML的顯式配置
建議盡可能使用自動化配置,以避免顯式配置所帶來的維護成本
如果確實需要顯式配置的話,應該優先選擇基於JavaConfig的配置,它比基於XML的配置更加強大、類型安全並且易於重構
02 裝配Bean