深入淺出spring IOC中四種依賴注入方式

深入淺出spring IOC中四種依賴注入方式

PS:前三種是我轉載的,第四種是現加的,按照原來的代碼模式
spring的核心思想是IOC和AOP,IOC-控制反轉,是一個重要的面向對象編程的法則來消減計算機程序的耦合問題,控制反轉一般分爲兩種類型,依賴注入和依賴查找,依賴什麼?爲什麼需要依賴?注入什麼?控制什麼?依賴注入和控制反轉是一樣的概念嗎?接觸新的知識,小編的腦袋中全是大大的問號,不過沒有關係,今天這篇博文,小編主要來簡單的介紹一下在spring IOC中依賴注入的方法。
依賴注入和控制反轉,目的是爲了使類與類之間解耦合,提高系統的可擴展性和可維護性。我們可以從以下幾個方面理解:
a、參與者都有誰?
b、依賴:誰依賴誰?爲什麼需要依賴?
c、注入:誰注入誰?又注入了什麼呢?
d、控制反轉:誰控制誰?控制什麼?爲什麼叫反轉呢?存在正轉嗎?

e、控制反轉和依賴注入是同一個概念嗎?我們需要弄明白上面的問題,這樣對於控制反轉和依賴注入的理解有大大的幫助。

首先:第一個問題,參與者都有誰?
1)對象
2)IOC/DI容器
3)某個對象的外部資源
第二問題:依賴,誰依賴誰?爲什麼需要依賴?
依賴嘛,很好理解的,對象依賴於IOC/DI容器,至於爲什麼要依賴呢?對象需要IOC/DI容器來提供對象需要的外部資源。
第三個問題:注入,誰注入誰?又注入了什麼呢?
顯而易見是IOC/DI容器注入對象,注入了what呢?肯定注入的是某個需要的東西那就是注入對象所需要的資源,肯定不會注入無關緊要的內容,你說呢?
第四個問題:控制反轉,誰控制誰?控制什麼?爲什麼叫反轉呢?存在正轉嗎?
控制反轉,控制什麼?肯定是IOC/DI容器控制對象,主要是控制對象實例的創建,反轉是相對於正向而言的,那麼什麼算是正向的呢?考慮一下常規情況下的應用程序,如果要在A裏面使用C,你會怎麼做呢?當然是直接去創建C的對象,也就是說,是在A類中主動去獲取所需要的外部資源C,這種情況被稱爲正向的。那麼什麼是反向呢?就是A類不再主動去獲取C,而是被動等待,等待IoC/DI的容器獲取一個C的實例,然後反向的注入到A類中。
第五個問題:控制反轉和依賴注入式同一個概念嗎?
依賴注入和控制反轉是對同一件事情的不同描述,從某個方面講,就是它們描述的角度不同。依賴注入是從應用程序的角度在描述,可以把依賴注入描述完整點:應用程序依賴容器創建並注入它所需要的外部資源;而控制反轉是從容器的角度在描述,描述完整點:容器控制應用程序,由容器反向的嚮應用程序注入應用程序所需要的外部資源。

瞭解了這些基本的概念,弄明白她們之間的聯繫和區別,能夠幫助我們更好的理解,接着小編來重點介紹一下依賴注入,在spring ioc中有三種依賴注入,分別是:
a、接口注入;
b、setter方法注入;
c、構造方法注入;

d、註解方法注入;
接着小編對這四種注入方式一一進行講解,通過demo的講解,希望能夠幫助小夥伴們更好的理解,不足之處還請多多指教。
接口注入

[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. public class ClassA {  
  2.   private InterfaceB clzB;  
  3.   public void doSomething() {  
  4.     Ojbect obj = Class.forName(Config.BImplementation).newInstance();  
  5.     clzB = (InterfaceB)obj;  
  6.     clzB.doIt();   
  7.   }  
  8. ……  
  9. }  

解釋一下上述的代碼部分,ClassA依賴於InterfaceB的實現,我們如何獲得InterfaceB的實現實例呢?傳統的方法是在代碼中創建 InterfaceB實現類的實例,並將賦予clzB.這樣一來,ClassA在編譯期即依賴於InterfaceB的實現。爲了將調用者與實現者在編譯期分離,於是有了上面的代碼。我們根據預先在配置文件中設定的實現類的類名(Config.BImplementation),動態加載實現類,並通過InterfaceB強制轉型後爲ClassA所用,這就是接口注入的一個最原始的雛形。

setter方法注入

setter注入模式在實際開發中有非常廣泛的應用,setter方法更加直觀,我們來看一下spring的配置文件:

[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <?xml version="1.0" encoding="UTF-8"?>    
  2. <beans xmlns="http://www.springframework.org/schema/beans"    
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.          xmlns:aop="http://www.springframework.org/schema/aop"    
  5.          xmlns:tx="http://www.springframework.org/schema/tx"    
  6.          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd    
  7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd    
  8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">    
  9.     
  10.     <!-- 使用spring管理對象的創建,還有對象的依賴關係 -->    
  11.     <bean id="userDao4Mysql" class="com.tgb.spring.dao.UserDao4MysqlImpl"/>    
  12.     
  13.     <bean id="userDao4Oracle" class="com.tgb.spring.dao.UserDao4OracleImpl"/>    
  14.         
  15.     <bean id="userManager" class="com.tgb.spring.manager.UserManagerImpl">    
  16.         <!-- (1)userManager使用了userDao,Ioc是自動創建相應的UserDao實現,都是由容器管理-->    
  17.         <!-- (2)在UserManager中提供構造函數,讓spring將UserDao實現注入(DI)過來 -->    
  18.         <!-- (3)讓spring管理我們對象的創建和依賴關係,必須將依賴關係配置到spring的核心配置文件中 -->    
  19.     
  20.         <property name="userDao" ref="userDao4Oracle"></property>    
  21.     </bean>    
  22.         
  23. </beans>    
  24.  
接着我們來看一下,setter表示依賴關係的寫法

[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import com.tgb.spring.dao.UserDao;    
  2.     
  3. public class UserManagerImpl implements UserManager{    
  4.     
  5.     private UserDao userDao;    
  6.     
  7.     //使用設值方式賦值    
  8.     public void setUserDao(UserDao userDao) {    
  9.         this.userDao = userDao;    
  10.     }    
  11.         
  12.     @Override    
  13.     public void addUser(String userName, String password) {    
  14.     
  15.         userDao.addUser(userName, password);    
  16.     }    
  17. }    

構造器注入

構造器注入,即通過構造函數完成依賴關係的設定。我們看一下spring的配置文件:

[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <?xml version="1.0" encoding="UTF-8"?>    
  2.     <beans xmlns="http://www.springframework.org/schema/beans"    
  3.              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.              xmlns:aop="http://www.springframework.org/schema/aop"    
  5.              xmlns:tx="http://www.springframework.org/schema/tx"    
  6.              xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd    
  7.                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd    
  8.                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">    
  9.         
  10.         <!-- 使用spring管理對象的創建,還有對象的依賴關係 -->    
  11.         <bean id="userDao4Mysql" class="com.tgb.spring.dao.UserDao4MysqlImpl"/>    
  12.         
  13.         <bean id="userDao4Oracle" class="com.tgb.spring.dao.UserDao4OracleImpl"/>    
  14.             
  15.         <bean id="userManager" class="com.tgb.spring.manager.UserManagerImpl">    
  16.             <!-- (1)userManager使用了userDao,Ioc是自動創建相應的UserDao實現,都是由容器管理-->    
  17.             <!-- (2)在UserManager中提供構造函數,讓spring將UserDao實現注入(DI)過來 -->    
  18.             <!-- (3)讓spring管理我們對象的創建和依賴關係,必須將依賴關係配置到spring的核心配置文件中 -->    
  19.         
  20.             <constructor-arg ref="userDao4Oracle"/>    
  21.         </bean>    
  22.             
  23.     </beans>    

我們再來看一下,構造器表示依賴關係的寫法,代碼如下所示:

[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1.  import com.tgb.spring.dao.UserDao;    
  2.         
  3.     public class UserManagerImpl implements UserManager{    
  4.         private UserDao userDao4Oracle;
  5.         
  6.         //使用構造方式賦值    
  7.         public UserManagerImpl(UserDao userDao4Oracle) {    
  8.             this.userDao4Oracle = userDao4Oracle;    
  9.         }    
  10.         
  11.         @Override    
  12.         public void addUser(String userName, String password) {    
  13.         
  14.             userDao.addUser(userName, password);    
  15.         }    
  16.     }    

註解注入

註解注入,即通過註解方式完成依賴關係的設定。我們看一下spring的配置文件:

[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <?xml version="1.0" encoding="UTF-8"?>    
  2. <beans xmlns="http://www.springframework.org/schema/beans"    
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.          xmlns:aop="http://www.springframework.org/schema/aop"    
  5.          xmlns:tx="http://www.springframework.org/schema/tx"    
  6.          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd    
  7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd    
  8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">    
  9.   

    <context:annotation-config/>//啓動spring註解模式

      
  10.     <!-- 使用spring管理對象的創建,還有對象的依賴關係 -->    
  11.     <bean id="userDao4Mysql" class="com.tgb.spring.dao.UserDao4MysqlImpl"/>    
  12.     
  13.     <bean id="userDao4Oracle" class="com.tgb.spring.dao.UserDao4OracleImpl"/>    
  14.         
  15.     <bean id="userManager" class="com.tgb.spring.manager.UserManagerImpl">    
  16.         <!--<property name="userDao" ref="userDao4Oracle"></property> --> //這段去掉  
  17.     </bean>    
  18.         
  19. </beans>    
  20.  

具體寫法:
  1. import com.tgb.spring.dao.UserDao;  
  2.  import javax.annotation.Resource;  //需要導入相關jar包
  3.         
  4.     @Resource(name="userDao4Oracle")
  5.      private UserDao userDao4Oracle;
  6.     
  7.      public class UserManagerImpl implements UserManager{    
  8.         private UserDao userDao4Oracle;
  9.         
  10.         
  11.         @Override    
  12.         public void addUser(String userName, String password) {    
  13.         
  14.             userDao.addUser(userName, password);    
  15.         }    
  16.     }    


接口注入 && setter注入 && 構造器注入
        接口注入:
接口注入模式因爲具備侵入性,它要求組件必須與特定的接口相關聯,因此並不被看好,實際使用有限。
Setter 注入:
對於習慣了傳統 javabean 開發的程序員,通過 setter 方法設定依賴關係更加直觀。如果依賴關係較爲複雜,那麼構造子注入模式的構造函數也會相當龐大,而此時設值注入模式則更爲簡潔。如果用到了第三方類庫,可能要求我們的組件提供一個默認的構造函數,此時構造子注入模式也不適用。
構造器注入:
在構造期間完成一個完整的、合法的對象。所有依賴關係在構造函數中集中呈現。依賴關係在構造時由容器一次性設定,組件被創建之後一直處於相對“不變”的穩定狀態。只有組件的創建者關心其內部依賴關係,對調用者而言,該依賴關係處於“黑盒”之中。
註解注入@Resource先會按照名稱到spring容器中查找,如果查找不到,就回退按照類型匹配,如果再沒有匹配到,就會拋出異常。如果在開發的時候,建議大家都是用@Resource(name=userDao),此時只能夠按照名稱匹配

小編寄語:該博文,小編主要介紹了控制反轉、依賴注入以及在spring中IOC的三種注入方式,配上demo進行講解,不足之處,還請各位小夥伴多多指教,其實小編覺得,無論是控制反轉還是依賴注入對編程帶來最大的影響不是從代碼上,而是思想上轉變,發生了“主從換位”的變化。應用程序原本是老大,要獲取什麼資源都是主動出擊,但是在IoC/DI思想中,應用程序就變成被動的了,被動的等待IoC/DI容器來創建並注入她所需要的資源了。這一舉動,有效的分離了對象和她所需要的外部資源,使得它們鬆散耦合,有利於功能複用,更重要的是使得程序的整個體系結構變得非常靈活。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章