javascript
《Spring实战》第四版读书笔记 第二章 装配Bean
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
在Spring中,對(duì)象無需自己查找或創(chuàng)建與其所關(guān)聯(lián)的其他對(duì)象。相反,容器負(fù)責(zé)把需要相互協(xié)作的對(duì)象引用賦予各個(gè)對(duì)象。
創(chuàng)建應(yīng)用對(duì)象之間協(xié)作關(guān)系的行為通常稱為裝配(wiring),這也是依賴注入的本質(zhì)。
2.1 Spring配置的可選方案
Spring提供了三種主要的裝配機(jī)制:
- 在XML中進(jìn)行顯式配置;
- 在Java中進(jìn)行顯式配置;
- 隱式的bean發(fā)現(xiàn)機(jī)制和自動(dòng)裝配。
作者建議盡可能的使用自動(dòng)裝配的機(jī)制。顯式配置越少越好,當(dāng)必須要顯式配置bean的時(shí)候(比如,有些源碼不是由你來維護(hù)的,而當(dāng)你需要為這些代碼配置bean的時(shí)候),推薦使用類型安全并且比XML更加強(qiáng)大的JavaConfig。最后,只有當(dāng)你想要使用便利的XML命名空間,并且在JavaConfig中沒有同樣的實(shí)現(xiàn)是才應(yīng)該使用XML。
2.2 自動(dòng)化裝配bean
Spring從兩個(gè)角度實(shí)現(xiàn)自動(dòng)化裝配:
- 組件掃描(component scanning):Spring會(huì)自動(dòng)發(fā)現(xiàn)應(yīng)用上下文中所創(chuàng)建的bean;
- 自動(dòng)裝配(autowiring):Spring自動(dòng)滿足bean之間的依賴。
2.2.1 創(chuàng)建可被發(fā)現(xiàn)的bean
在類上使用@Component注解,這個(gè)注解表明該類會(huì)作為組件類,并告知Spring要為這個(gè)類創(chuàng)建bean。
組件掃描默認(rèn)是不啟用的,還需要顯式配置一下Spring,從而命令它去尋找?guī)в?#64;Component注解的類并為其創(chuàng)建bean。
@Configuation @ComponentScan public class CDPlayerConfig { }如果沒有其他配置,@ComponentScan默認(rèn)會(huì)掃描與配置類相同的包。
如果想使用XML來啟用組件掃描,可以使用Spring context命名空間的context:component-scan元素。
<?xml version="1.0" encoding="UTF-8"?> <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.springframeword.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="soundsystem"/> </beans>測(cè)試組件掃描代碼:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=CDPlayerConfig.class) public class CDPlayerText {@Autowiredprivate CompactDisc cd;@Testpublic void cdShouldNotBeNull() {assertNotNull(cd)} }CDPlayerTest使用了Spring的SpringJUnit4ClassRunner,以便在測(cè)試開始的時(shí)候自動(dòng)創(chuàng)建Spring的應(yīng)用上下文。注解@ContextConfiguration會(huì)告訴它需要在CDPlayerConfig中加載配置。
2.2.2 為組件掃描的bean命名
在組件掃描中如果沒有明確的設(shè)置ID,Spring會(huì)根據(jù)類名為其指定一個(gè)ID。這個(gè)bean所給定的ID是首字母變?yōu)樾懙念惷?/p>
如果想為這個(gè)bean設(shè)置不同的ID,需要將其作為值傳遞給@Component注解。
@Component("lonelyHeartsClub") public class SgtPeppers implements CompactDisc { }另外一種bean命名方式使用Java依賴注入規(guī)范中提供的@Named注解:
@Named("lonelyHeartsClub") public class SgtPeppers implements CompactDisc { }Spring支持將@Named作為@Component注解的替代方案。兩者之間由一些細(xì)微的差異,但在大多數(shù)場(chǎng)景中可以互換。
本書的作者更喜歡@Component。
2.2.3 設(shè)置組件掃描的基礎(chǔ)包
如果沒有為@ComponentScan設(shè)置屬性,按照默認(rèn)規(guī)則,它會(huì)以配置類所在的包作為基礎(chǔ)包來掃描逐漸。
如果想掃描不同的包,在@ComponentScan的value屬性中指定包名即可。
@Configuraion @ComponentScan("soundsystem") public class CDPlayerConfig{ }如果想更加清晰的表明所設(shè)置的是基礎(chǔ)包,可以通過basePackages屬性進(jìn)行配置:
@Configuration @ComponentScan(basePackages="soundsystem") public class CDPlayerConfig{}basePackages屬性可以設(shè)置多個(gè)包,賦值一個(gè)數(shù)組即可:
@Configuration @ComponentScan(basePackages={"soundsystem", "video"}) public class CDPlayerConfig { }除了將包設(shè)置為簡(jiǎn)單的String類型外,@ComponentScan哈提供了另外一種方法,將其指定為包中所包含的類或接口:
@Configuration @ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class}) public class CDPlayerConfig { }2.2.4 通過為bean添加注解實(shí)現(xiàn)自動(dòng)裝配
可以在構(gòu)造器、setter方法、任何方法上使用@Autowired注解,Spring會(huì)嘗試滿足方法參數(shù)上所聲明的依賴。假如有且只有一個(gè)bean匹配依賴需求,那么這個(gè)bean將會(huì)被裝配進(jìn)來。
如果沒有匹配的bean,那么在應(yīng)用上下文創(chuàng)建的時(shí)候會(huì)拋出異常。可以將@Autowired的required屬性設(shè)置為false,此時(shí)Spring會(huì)嘗試自動(dòng)裝配,但是如果沒有匹配的bean的話該屬性將會(huì)為null。
如果有多個(gè)bean都滿足依賴關(guān)系,Spring將會(huì)拋出異常。
@Autowired是Spring特有的注解。可以使用@Inject注解替代。
2.3 通過Java代碼裝配Bean
顯式的裝配方式有兩種:Java和XML。
2.3.1 創(chuàng)建配置類
@Configuration注解表明這個(gè)類是一個(gè)配置類,該類應(yīng)該包含在Spring應(yīng)用上下文中如何創(chuàng)建bean的細(xì)節(jié)。
2.3.2 聲明簡(jiǎn)單bean
要在JavaConfig中聲明bean,需要編寫一個(gè)方法,這個(gè)方法會(huì)創(chuàng)建所需類型的實(shí)例,然后給這個(gè)方法添加@Bean注解。
@Bean注解會(huì)告訴Spring這個(gè)方法將返回一個(gè)對(duì)象,該對(duì)象要注冊(cè)為Spring應(yīng)用上下文中的bean。方法體中包含了最終產(chǎn)生bean實(shí)例的邏輯。
默認(rèn)情況下,bean的ID與方法名一致。如果想為其設(shè)置一個(gè)不同的名字,可以重命名該方法,也可以通過@Bean的name屬性指定。
2.3.3 借助JavaConfig實(shí)現(xiàn)注入
在JavaConfig中裝配bean的最簡(jiǎn)單方式就是引用創(chuàng)建bean的方法。在方法上添加了@Bean注解,Spring將會(huì)攔截所有對(duì)它的調(diào)用,并確保直接返回該方法所創(chuàng)建的bean,而不是每次都對(duì)其進(jìn)行實(shí)際的調(diào)用。
通過調(diào)用方法引用bean的方式有點(diǎn)令人困惑。還有一種理解起來更簡(jiǎn)單的方式:
@Bean public CDPlayer cdPlayer(CompactDisc compactDisc) {return new CDPlayer(compactDisc); }cdPlaye()方法請(qǐng)求一個(gè)CompactDisc作為參數(shù),當(dāng)Spring調(diào)用cdPlayer()創(chuàng)建CDPlayer bean的時(shí)候,它會(huì)自動(dòng)裝配一個(gè)CompactDisc到配置方法之中。
通過這種方式引用其他的bean通常是最佳的選擇,因?yàn)樗粫?huì)要求將CompactDisc聲明到同一個(gè)配置類之中。在這里甚至沒有要求CompactDisc必須要在JavaConfig中聲明,實(shí)際上它可以通過組件掃描功能自動(dòng)發(fā)現(xiàn)或者通過XML來進(jìn)行配置。可以將配置分散到多個(gè)配置類、XML文件以及自動(dòng)掃面和裝配bean之中。
2.4 通過XML裝配Bean
2.4.1 創(chuàng)建XML配置規(guī)范
在XML配置中,要?jiǎng)?chuàng)建一個(gè)XML文件,并且要以<beans>元素為根。
<?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.springframeword.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context"><!-- 配置詳情 --> </beans>2.4.2 聲明一個(gè)簡(jiǎn)單的<bean>
<bean>元素類似于JavaConfig中的@Bean注解。
如果沒有給定ID,所以這個(gè)bean將會(huì)根據(jù)全限定類名來進(jìn)行命名。例如“soundsystem.SgtPeppers#0“,其中“#0”是一個(gè)計(jì)數(shù)形式,用來區(qū)分相同類型的其他bean。
2.4.3 借助構(gòu)造器注入初始化bean
構(gòu)造器注入有兩種基本的配置方案可供選擇:
- <constructon-arg>元素;
- 使用Spring 3.0 所引入的c-命名空間。
構(gòu)造器注入bean引用
<bean id="cdPlayer" class="soundsystem.CDPlayer"><constructor-arg ref="compactDisc"/> </bean>c-命名空間的schema:
xmlns:c="http://www.springframework.org/schema/c" <bean id="cdPlayer" class="soundsystem.CDPlayer" c:cd-ref="compactDisc" />屬性以c:開頭,也就是命名空間的前綴。接下來是要裝配的構(gòu)造器參數(shù)名,在此之后是-ref,這是一個(gè)命名約定,告訴Spring正在裝配的是一個(gè)bean應(yīng)用。
可以使用參數(shù)在整個(gè)參數(shù)列表中的位置來替代參數(shù)名:
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:_0-ref="compactDisc" />因?yàn)樵赬ML中不允許數(shù)字作為屬性的第一個(gè)字符,因此必須要添加一個(gè)下劃線作為前綴。
如果只有一個(gè)參數(shù),不用標(biāo)示參數(shù):
<bean id="cdPlayer" class="soundsystem.CDPlayer"c:_-ref="compactDisc" />將字面量注入到構(gòu)造器中
<bean id="compactDisc"class="soundsystem.BlankDisc"><constructor-arg value="sgt. Pepper" /> </bean>依然使用<constructor-arg>元素進(jìn)行注入,但是使用了value屬性。
<bean id="compactDisc"class="soundsystem.BlankDisc"c:_title="sgt. Pepper"/>使用c-命名空間裝配字面量與裝配引用的區(qū)別在于屬性名中去掉了-ref后綴。
裝配集合
<constructor-arg>可以將集合裝配到構(gòu)造器參數(shù)重,而c-命名空間不能。
可以使用<null/>元素將null傳遞給構(gòu)造器。
可以使用<list>元素聲明一個(gè)列表:
<constructor-arg><list><value>.....</value><value>......</value></list> </constructor-arg><list>元素是<constructor-arg>的子元素,這表明一個(gè)包含值的列表將會(huì)傳遞到構(gòu)造器中。其中<value>元素用來指定列表中的每個(gè)元素。
與之類似,可以使用<ref>元素代替<value>,實(shí)現(xiàn)bean引用列表的裝配。
可以用相同的方式使用<set>元素。<set>和<list>元素的區(qū)別不大,無論在哪種情況下,<set>或<list>都可以用來裝配List、Set甚至是數(shù)組。
2.4.4 設(shè)置屬性
<property>元素為屬性的setter方法所提供的功能與<constructor-arg>元素為構(gòu)造器提供的功能是一樣的。
Spring提供了p-命名空間作為<property>元素的替代方案。p-命名空間的schema:
xmlns:p="http://www.springframework.org/schema/p"util-命名空間所提供的功能之一是util:list元素,它會(huì)創(chuàng)建一個(gè)列表的bean。
xmlns:util="http://www.springframework.org/schema/util" <util:list id="trackList"><value>......</value><value>.....</value> </util:list>下表展示了Spring util-命名空間中的元素
| util:constant | 引用某個(gè)類型的public static域,并將其暴露為bean |
| util:list | 創(chuàng)建一個(gè)java.util.List類型的bean,其中包含值或引用 |
| util:map | 創(chuàng)建一個(gè)java.util.Map類型的bean,其中包含值或引用 |
| util:properties | 創(chuàng)建一個(gè)java.util.Propertie類型的bean |
| util:property-path | 引用一個(gè)bean的屬性(或內(nèi)嵌屬性),并將其暴露為bean |
| util:set | 創(chuàng)建一個(gè)java.util.Set類型的bean,其中包含值或引用 |
2.5 導(dǎo)入和混合配置
2.5.1 在JavaConfig中引用XML配置
使用@Import注解引用其他JavaConfig配置,使用@ImportResource注解引入XML配置。
@Configuration @Import(CDPlayerConfig.class) @ImportResource("classpath:cd-config.xml") public class SoundSystemConfig {}2.5.2 在XML配置中引用JavaConfig
在XML中可以使用<import>元素來引用其他XML配置。
將JavaConfig作為bean使用<bean>元素導(dǎo)入XML配置文件。
轉(zhuǎn)載于:https://my.oschina.net/u/2453016/blog/1532349
總結(jié)
以上是生活随笔為你收集整理的《Spring实战》第四版读书笔记 第二章 装配Bean的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 并查集(Union-Find)算法介绍
- 下一篇: 如何编写更好的SQL查询:终极指南-第三