Spring框架的核心就是控制反轉(zhuǎn)(Inversion of Control)和依賴注入(Dependency Injection),通過(guò)這兩方面來(lái)實(shí)現(xiàn)松耦合。
??? 使用IoC,對(duì)象是被動(dòng)的接受依賴類,而不是自己主動(dòng)的去找。容器在實(shí)例化的時(shí)候主動(dòng)將它的依賴類注入給它。可以這樣理解:控制反轉(zhuǎn)將類的主動(dòng)權(quán)轉(zhuǎn)移到接口上,依賴注入通過(guò)xml配置文件在類實(shí)例化時(shí)將其依賴類注入。通過(guò)下面的實(shí)例來(lái)逐步的理解:
??? 首先假設(shè)有一個(gè)需求,類Business需要調(diào)用類Dependency的方法f(),按照日常的做法,得到下面的代碼:
//**類Dependency**
public class Dependency {
??? public void f() {};
}
//**類Business**
public? class Business {
??? Dependency d;
??? public Business() {
??? d = new Dependency();
??? }
??? public void doSth() {
??????? d.f();
??? }
}
??? 對(duì)上述實(shí)現(xiàn)做出如下修改:
??? 首先,將Business里的Dependency實(shí)例的獲得該為setter方式,其次,將Dependency類改為某個(gè)接口的實(shí)現(xiàn)。故可以得到下面新的代碼:
//**接口IDependency**
public inte***ce IDependency {
??? void f();
}
//**類Dependency**
public class Dependency {
??? public void f() {};
}
//**類Business**
public? class Business {
??? IDependency d;
??? public Business() {}
??? public void doSth() {
???? d.f();
??? }
??? public void setDependency(IDependency d) {
??????? this.d = d;
??? }
}
??? 在新的代碼中,首先Business的變量d可以接收任何IDependency的實(shí)例,另外,Dependency的實(shí)例不是通過(guò)Business來(lái)獲得,而是通過(guò)setter(也可以用構(gòu)造器)來(lái)由外部傳給它。這似乎跟我們往常的代碼沒什么不同,但這已經(jīng)是一個(gè)良好的設(shè)計(jì)。關(guān)鍵就是Dependency的實(shí)例如何從外部注入給Business呢?
這就要通過(guò)xml來(lái)實(shí)現(xiàn)了。
??? 創(chuàng)建一個(gè)SpringFirst.xml,進(jìn)行簡(jiǎn)單的配置:
<beans>
??? <bean id = "dependency" class = "aopfirst.business.Dependency" />
??? <bean
??????? id = "business"
??????? class = "aopfirst.business.Business"
??? >
??????? <property name = "dependency">
??????????? <ref bean = "dependency" />
??????? </property>
??? </bean>
</beans>
??? 這個(gè)配置文件里將Dependency類和Business類加入,并將Dependency作為Business的一個(gè)參數(shù)。
??? 單有了這個(gè)xml文件還不夠,還需要一個(gè)測(cè)試類來(lái)加載該xml文件,spring提供了現(xiàn)成的API,在加載上面的xml的時(shí)候,就進(jìn)行了如下工作:實(shí)例化Dependency類,實(shí)例化Business類,并將Dependency的實(shí)例作為參數(shù)賦給了Business實(shí)例的
setDependency()方法。下面是該測(cè)試程序:
public class StartServer {
??? public static void main(String [] args) {
???? ClassPathResource cr = new ClassPathResource("SpringFirst.xml");
???? BeanFactory factory = new XmlBeanFactory(cr);
???? Business b = (Business)factory.getBean("business");
???? b.doSth();
??? }
}
??? 上面的程序加載了xml以后,獲得id為"business"的bean,即Business類的實(shí)例,并調(diào)用了其doSth()方法。由此可見,Business的依賴類Dependency是通過(guò)xml來(lái)注入的,而且Business是通過(guò)接口IDependency來(lái)接收Dependency實(shí)例。因此,當(dāng)我們又有新的IDependency的實(shí)現(xiàn)時(shí),只需要修改xml文件即可,測(cè)試程序只需要根據(jù)xml里的id值來(lái)獲得需要的參數(shù)。
??? 總結(jié)上面的例子,對(duì)控制反轉(zhuǎn)和依賴注入已經(jīng)能理解了。依賴類(Dependency)是通過(guò)外部(xml)來(lái)注入的,而不是由使用它的類(Business)來(lái)自己制造,這就是依賴的注入。另一方面,Business對(duì)類Dependency的依賴轉(zhuǎn)移到對(duì)接口IDependency的依賴,控制權(quán)由類轉(zhuǎn)移到了接口,即由"實(shí)現(xiàn)"轉(zhuǎn)移到"抽象"中。這就是控制反轉(zhuǎn)。