控制反轉

Spring IOC

     IOC(Inversion of Control),譯作反轉控制,其功能是將類之間的依賴轉移到外部的配置文件中, 避免在調用類中硬編碼實現類,因此也被稱作依賴注入(Dependency Injection)。在以往的開發中, 通常利用工廠模式(Factory)來解決此類問題,其實不管是工廠模式還是依賴注入,調用類與實現類不可 能沒有任何依賴,工廠模式中工廠類通常根據參數來判斷該實例化哪個實現類,Spring IOC將需要實例的 類在配置文件文件中配置。使用Spring IOC能得到工廠模式同樣的效果,而且編碼更加簡潔。看段代碼比較 一下:

一、用工廠模式來實現

例 1.1. Product.java

public interface Product { public void execute();}   例 1.2. ConcreteProductA.java

public class ConcreteProductA implements  Product{ public void execute() {  ... }}   例 1.3. ConcreteProductB.java

public class ConcreteProductB implements  Product{ public void execute() {  ... }}   例1.4. Factory.java

public class Factory{  public Product CreateProduct(object param) {  return ConstructObjects(param); }  private Product ConstructObjects(object param) {  ... }}   例 1.5. Client.java(調用類)

public class Client{ public Client() {  //實例化ConcreteProductA  Product product = Factory.CreateProduct(paramA);    //實例化ConcreteProductB  Product product = Factory.CreateProduct(paramB);  ... }}   在ConstructObjects方法中設定實例化實現類的邏輯,這樣對於調用類來說,不直接實例化實現類,縱然實現類發生變化, 調用代碼仍然可以不作修改,給維護與擴展帶來便利。

二、Spring IOC實現

例 1.6. SpringConfig.xml

<bean id="productA" class="ConcreteProductA" /><bean id="productB" class="ConcreteProductB" />   例 1.7. Client.java(調用類)

public class Client{ public Client() {  //實例化ConcreteProductA  Product product = (Product)InitSpring.getObject("productA");    //實例化ConcreteProductB  Product product = (Product)InitSpring.getObject("productB");  ... }}   調用代碼中沒有硬編碼實現類,比較工廠模式,少了Factory類。

Spring爲依賴注入提供三種實現方式:接口注入、設值注入、構造注入。利用這些可以靈活的解決 類之間的依賴關係,讓你爲所欲爲的組裝代碼。與其說Spring IOC是一個工具,還不如說搭建了一 個思想的舞臺。繼續看代碼:

來實現一個操作多個數據源的切換

例 1.8. DataSource.java

public class DataSource{  private String driverClassName;  private String url;  private String username;  private String password;  public String getDriverClassName()  {  return this.driverClassName;  }  public void setDriverClassName(String driverClassName)  {  this.driverClassName = driverClassName;  }  public String getUrl()  {  return this.url;  }  public void setUrl(String url)  {  this.url = url;  }  public String getUsername()  {  return this.Username;  }  public void setUsername(String username)  {  this.username = username;  }  public String getPassword()  {  return this.password;  }  public void setPassword(String password)  {  this.password = password;  }}   例 1.9. DataAccessor.java

public class DataAccessor{ private DataSource dataSource; public void setDriver(DataSource dataSource) {  this.dataSource = dataSource; } public void save(String sql) {  Statement s = getStatement();  try        {            s.getConnection().setAutoCommit(false);   int rows = s.executeUpdate(sql);         s.getConnection().commit();  }        catch(Exception e)        {   s.getConnection().rollback();   ...         }  finally  {   ...  } } private Statement getStatement() {  Statement s;  try  {   Class.forName(dataSource.getDriverClassName()).newInstance();            java.sql.Connection conn =    java.sql.DriverManager.getConnection(dataSource.getUrl(),dataSource.getUser(),dataSource.getPassword());            try            {                s = c.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);            }  }  catch(Exception e)  {   ...  }  return s; }}   例 1.10. BussinessA.java

public class BussinessA{ private DataAccessor dao; public void setDao(DataAccessor dao) {  this.dao = dao; } public void execute() {  dao.save("insert into tb1 ..."); }}   例 1.11 BussinessB.java

public class BussinessB{ private DataAccessor dao; public void setDao(DataAccessor dao) {  this.dao = dao; } public void execute() {  dao.save("insert into tb2 ..."); }}   全部代碼就這樣了,執行BussinessA.java、BussinessB.java代碼即可完成數據插入操作,從代碼中看, 這兩個類具體操作的是什麼數據庫?什麼樣的操作細節?讓你失望了,代碼中找不到這樣的關聯,看配置文件吧:

例 1.12. SpringConfig.xml

<bean id="dataSourceA" class="DataSource" destroy-method="close">        <property name="driverClassName"><value>org.gjt.mm.mysql.Driver</value></property>        <property name="url">   <value>jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=GBK</value>        </property>        <property name="username"><value>root</value></property>        <property name="password"><value></value></property> </bean> <bean id="dataSourceB" class="DataSource" destroy-method="close">        <property name="driverClassName"><value>org.gjt.mm.mysql.Driver</value></property>        <property name="url">   <value>jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=GBK</value>        </property>        <property name="username"><value>root</value></property>        <property name="password"><value></value></property> </bean><bean id="daoA" class="DataAccessor">  <property name="dataSource">   <ref local="dataSourceA"/>  </property></bean><bean id="daoB" class="DataAccessor">  <property name="dataSource">   <ref local="dataSourceB"/>  </property></bean><bean id="bussinessA" class="BussinessA">  <property name="dao">   <ref local="daoA"/>  </property></bean><bean id="bussinessB" class="BussinessB">  <property name="dao">   <ref local="daoB"/>  </property></bean>   看完配置文件應該明白了,這裏承擔了所有的依賴關係。

首先,我們通過設值注入方法設置數據源相關參數

然後,我們將數據源實例注入給數據訪問類

最後,我們爲每個具體業務類注入相應訪問器

是不是感覺想玩積木似的,在組裝你的代碼?

例 1.13. DaoTest.java

public void testSave(){ BussinessA bussinessA = (BussinessA)InitSpring.getObject("bussinessA"); bussinessA.execute(); bussinessB bussinessB = (BussinessB)InitSpring.getObject("bussinessB"); bussinessB.execute();}   執行這段測試代碼,數據庫Test1、Test2中tb1、tb2表將分別插入對應的數據,從實現代碼來看操作多個數據庫和 操作一個數據庫完全一樣,即使當數據源,數據訪問類不斷變化,應用代碼也可以做到不用任何修改。

希望看完本章節的內容能讓讀者與我共鳴,Spring IOC是一種優雅的思想,藉助它發揮你無窮的想象吧。

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/lip8654/archive/2007/04/30/1592637.aspx

發佈了12 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章