????有部分Java開發(fā)者對IoC和Di的概念有些混淆,認(rèn)為二者是對等的,實際上IoC其實有兩種方式:一種就是DI,而另一種是DL(Dependency Lookup,依賴查找).
????前者是當(dāng)前軟件實體被動接受其依賴的其他自減被IoC容器注入,而后者則是當(dāng)前軟件試題主動去某個服務(wù)注冊地查找起依賴的服務(wù),概念之間的關(guān)系如圖所示:
? ? 我們通常提到的SpringI哦C,實際上是指Spring框架提供的IoC容器實現(xiàn)(IoC Container),而使用Spring IoC容器的一個典型代碼片段就是:
public class App {
????public static void main(String[] args) {
????????????ApplicationContext context = new FileSystemXmlApplicationContext("...");
? ? ? ? ? ? //...
????????????MockServoce service = context.getBean(MockService.class); ???????????
?????????????service.doSomething();
????????}
}
????????任何一個使用Spring框架構(gòu)建的獨立的Java應(yīng)用(Standalone Java Application),通常都會存在一行類似于"context.getBean(...);"的代碼中,實際上,折行代碼做的就是DL的工作,而構(gòu)建的任何一種IoC容器背后(比如BeanFactory或者ApplicationContent)發(fā)生的事情.則更多是DI的過程(也可能有部分DL的邏輯用于對接遺留系統(tǒng)).
? ? Spring的IoC容器中發(fā)生的事情其實也很簡單,總結(jié)下來即兩個階段:
(1)收集和注冊Bean
(2) 分析和組裝Bean
階段一:收集和注冊Bean
????????第一個階段可以認(rèn)為是構(gòu)建和收集bean定義的階段饮怯,在這個階段中嵌戈,我們可以通過XML或者JavaConfig代碼的方式定義一些bean,然后通過手動組裝或者讓容器基于某些機(jī)制自動掃描的形式芦拿,將這些bean定義收集到IoC容器中桐磁。
? ? ? ? 假設(shè)我們以XML配置的形式來收集并注冊單一Bean,一般形式如下:
<bean id="mockService" class="..MockServiceImpl">
...
</bean>l
? ? ? 如果嫌逐個手機(jī)Bean定義麻煩,想批量地注冊到IoC容器中,我們也可以通過XML Schema形式的配置進(jìn)行批量掃描并采集和注冊:
<context:component-scan base_package=""com.keevol">
階段二:分析和組裝
????????當(dāng)?shù)谝浑A段完成后,我們可以先暫時認(rèn)為IoC容器中充斥著一個個獨立的Bean,它們之間沒有任何關(guān)系.但實際上,它們之間是有依賴關(guān)系的,所以,IoC容器在第二階段要干的事情就是分析這些已經(jīng)在IoC容器之中的Bean,然后根據(jù)它們之間的依賴關(guān)系先后組裝它們.如果IoC容器發(fā)現(xiàn)某個Bean依賴另一個Bean,它就會將這另一個Beann注入給依賴它的那個Bean,直到所有Beand的依賴都注入完成,所有Bean都"整裝待發(fā)",這個IoC容器的工作即算完成.
? ? ? ? 至于分析和組裝的依據(jù),Spring框架最早是通過XML配置文件的形式在I描述Bean與Bean之間的關(guān)系的,隨著Java業(yè)界研發(fā)技術(shù)和理念的轉(zhuǎn)變,預(yù)計Java代碼和Annotation元信息的描述方式也日漸興盛(比如@Autowired和@Inject),但是不管是用哪種方式,都只是為了簡化綁定邏輯描述的各種"表象",最終都是為本階段的最終目的服務(wù).
提示:
????????很多Java開發(fā)者一定認(rèn)為Spring的XML配置文件是一種配置(Configration),但本質(zhì)上,這些配置文件更應(yīng)該是一種代碼形式,XML在這里其實可以看作一種DSL,它用來表述的是Bean與Bean之間的依賴綁定關(guān)系,諸君還記得沒有IoC容器的年代和自己寫代碼新建(nenw)對象并配置(set)依賴.
? ? ? ? ? ? ?