輕鬆瞭解Spring中的控制反轉和依賴注入(一)

  咱們回顧一下計算機的發展史,從最初第一臺計算機的佔地面積達170平方米,重達30噸,到現現在的我的筆記本,事物更加輕量功能卻更加豐富,這是事物發展過程當中的一個趨勢,在技術領域中一樣也是如此,企業級JavaBean(Enterprise JavaBean ,EJB)在建立之初是很是成功,可是時間一久人們便開始追逐更加方便更加簡易和輕量級的技術框架實現,因而Spring就應運而生,而且Spring一直開始不斷地涉及到其餘領域(這裏就再也不多詳談了),而Spring的精髓當中就包括控制反轉和依賴注入。html

 淺談控制反轉(Inversion of Control,IOC

  咱們首先先來了解一下控制二字,也就是在控制「」轉的狀況下,在任何一個有請求做用的系統當中,至少須要有兩個類互相配合工做,在一個入口類下使用new關鍵字建立另外一個類的對象實例,這就比如在面向對象編程的思想下,「我「充當一個入口類,在這個入口類中,我每次吃飯的時候都要買一雙一次性筷子(每一次使用都要new一次),在這樣的關係下,是」我「(即調用者)每次都要」主動「去買一次性筷子(另外一個類),我對筷子說你老老實實的過來個人手上,是我控制了筷子,那好,在這種控制正轉的關係下,放在現實生活當中,確定是不現實的,並且人是懶惰的,他總會去創造出更加方便本身生活的想法,更確切的作法是,買一雙普通的筷子(非一次性),把他放在一個容器當中(在Spring中叫作IOC容器),你須要使用的時候就對容器說:IOC我想要用筷子(向容器發出請求),接着筷子就會」注入「到的手上,而在這個過程中,你再也不是控制方,反而演變成一名請求者(雖然自己仍是調用者),依賴於容器給予你資源,控制權坐落到了容器身上,因而這就是人們俗稱的控制反轉spring

 初涉依賴注入(Dependency Injection)  

  一樣接着上面的例子,在控制反轉的統一下,筷子是怎麼來到個人手上(即咱們是如何得到請求的類),這就是一個依賴注入的過程。編程

 

 再談IOC與DI

  設計原則中好萊塢原則描述到,「別找咱們,咱們找你」,百度百科上對這點描述是「不要給咱們打電話,咱們會給你打電話(don‘t call us, we‘ll call you)」這是著名的好萊塢原則。在好萊塢,把簡歷遞交給演藝公司後就只有回家等待。由演藝公司對整個娛樂項的徹底控制,演員只能被動式的接受公司的差使,在須要的環節中,完成本身的演出。這一點完美的提現了在IOC身上,IOC所注重的是設計思想上,從一個常規的建立對象的作法,即new一個對象,轉變成向IOC容器遞交」簡歷「,被動的等待IOC容器返回資源給你。控制反轉即指的是」演藝公司控制演員「,而說到依賴,則是「演員須要公司混飯」,咱們所需求的對象,須要依賴容器來得到,這個過程便是依賴注入。本質上IOC和DI是同一思想下不一樣維度的表現app

 代碼實現

  既然說在控制反轉中獲取資源的過程叫作依賴注入,那麼這裏代碼實現也是專一於依賴注入。依賴注入有3種方式,分別爲構造注入,設置注入,接口注入。框架

  1.接口注入:在接口中定義要注入的信息,並經過接口來完成注入。(Spring不支持這種注入方式--不支持的緣由是--Spring聲稱其是非入侵式的《離開這個框架也能活》,若是使用接口注入的話,就違背了這一原則),這裏不作代碼實現講解。ide

  2.setter注入函數

  咱們先脫離Spring來實現setter注入,分兩步,第一步咱們先看看在常規的作法下類之間的關係,第二步使用IOC來進行設計類,對比一下之間的差異。this

  在常規的作法下spa

public class UserDao{
   public void addUser(String username)
{
   System.out.println("添加用戶:"+username);  
}  
}
public class UserMessage {
   String username="demo";
   UserDao userDao;
   public UserMessage(){
   userDao=new UserDao();  
}      
   public void addUser(){
  userDao.addUser(username);  
}  
}

  

public class test{
  UserMessage userMessage=new UserMessage();
  userMessage.addUser();
}

  這上面的代碼存在一個缺陷,因爲在UserMessage內部建立了UseDao對象,這就形成了兩個類之間的耦合度較高,當項目經理想要用另一個Dao類的方法來實現addUser的時候,這個時候我就須要修改User Message的代碼,從新new另外一個類,若是系統中有一百個地方用到這個類,那咱們這些地方都要所有修改,出現Bug的機率將大大增長,而後過了一陣子,項目經理又說我想換回之前的Dao類了……設計

  下面咱們看看IOC設計的實現

public interface UserDao{
  void addUser(String username);      
}
public class UserDaoImpl implements UserDao{
    @Override    
    public void addUser(String username)
{
    System.out.println("添加用戶:"+username);  
}  
}

 

public class UserMessage{    
    
    private UserDao userDao;    
    
    //使用設值方式賦值    
    public void setUserDao(UserDao userDao) {    
        this.userDao = userDao;    
    }    
    public void addUser(String userName, String password) {    
      
        userDao.addUser(userName);    
    }    
}   

  

public class test{
    public static void main(String[] args) {
        UserDao userDao =new UserDaoImpl();
        UserMessage userMessage=new UserMessage();
        userMessage.setUserDao(userDao);
    }
}

 

  咱們仔細觀察這裏的作法, UserDao userDao=new UserDaoImpl()作法,這裏就不得不提到了多態,即父類能夠引用子類的方法,在這裏造成的一個效果就是下降了User Message和UserDao的耦合度。由於UserMessage和UserDao之間僅存在作什麼事(addUser方法)的聯繫,User Message並不瞭解UserDaoImpl的實現方式。當咱們須要換另外一種UserDao的實現類的話,咱們只須要修改test類下的第一行的代碼就能夠了,UserMessage內部並不須要修改。

  再想一想,讀者可能會說不對啊,你說的控制反轉和依賴注入須要向容器請求資源,這個容器並無在上面提現出來啊,下面咱們就講解一下Spring 中是如何作到注入的。

  

  <!-- 使用spring管理對象的建立,還有對象的依賴關係 -->    
<bean id="userManager" class="scau.zzf.service.UserMessage">    
        <!-- (1)UserMessageImpl使用了userDao,Ioc是自動建立相應的UserDao實現,都是由容器管理-->    
        <!-- (2)在UserMessageImpl中提供構造函數,讓spring將UserDao實現注入(DI)過來 -->    
        <!-- (3)讓spring管理咱們對象的建立和依賴關係,必須將依賴關係配置到spring的核心配置文件中 -->    
        <property name="userDao" ref="UserDao"></property>   
    <!-- 構造注入 -->
    <!-- <constructor-arg ref="userDao"/>  --> 
    </bean>   
<bean id="UserDao" class="scau.zzf.Dao.UserDao">
    
</bean>    

 

  首先咱們須要裝配Bean,即在Spring容器中將Bean進行配置後,而後返回Bean對象實例。咱們能夠經過XmlBeanFactory讀取咱們xml文件,從而獲取相關的Bean信息。

public class test {
    public static void main(String[] args) throws Exception {
    BeanFactory factory=new XmlBeanFactory(new FileSystemResource("src/appllication.xml"));
        UserMessage userMessage=(UserMessage)factory.getBean("UserMessage");
        userMessage.add("德瑪西亞");

    }
}

  在實際應用當中,咱們並不會手動去讀取Xml中的信息或者加載配置文件,Spring底層已經幫我作好了這些,也就是在實際應用當中,咱們就只是須要發送一個請求而已,固然瞭解這麼一個過程仍是頗有必要的。

  下面再簡單講解一下如何經過註解來實現注入。

@Configuration
public class UserConfig {
    @Bean
    public UserDao getUserDao(){
        return new UserDao();
    }
    @Bean
    public UserMessage getUserMessage(){
        return new UserMesssgae(getUserDao);
    }
}
@Configuration的做用是使整個類成爲一個配置類,@Bean註解會告訴Spring這個註解下的方法將會返回一個對象,這個對象要註冊維Spring應用上下文的Bean。在默認狀況下,Spring的Bean都是單例的,也就是再上面的例子當中,不管咱們使用多少次getUserDao(),結果返回的對象至始至終都是相同的。關於JavaConfig的配置進一步相關說明,讀者能夠前往筆者的另外一篇文章《更加優雅的配置SSH》中進行參考。
  轉載請說明原文連接:http://www.cnblogs.com/xxzhuang/p/5948902.html 多謝合做。
相關文章
相關標籤/搜索