1. 程式人生 > 其它 >Spring原理與原始碼分析系列(一)- Spring IoC入門

Spring原理與原始碼分析系列(一)- Spring IoC入門

一、Spring簡介

什麼是Spring

 • 輕量:Spring是輕量級的,基本的版本大小為2MB
   • 控制反轉:Spring通過控制反轉實現了鬆散耦合,物件們給出它們的依賴,而不是建立或查詢依賴的物件們。
 • 面向切面的程式設計AOP:Spring支援面向切面的程式設計,並且把應用業務邏輯和系統服務分開。
 • 容器:Spring包含並管理應用中物件的生命週期和配置
 • MVC框架: Spring-MVC
 • 事務管理:Spring提供一個持續的事務管理介面,可以擴充套件到上至本地事務下至全域性事務JTA
 • 異常處理:Spring提供方便的API把具體技術相關的異常


Spring框架概述
Spring Framework由約20個模組組成的特徵組成。這些模組分為核心容器,資料訪問/整合,Web,AOP,Instrumentation,Messaging和Test,如下圖所示。


• (1)Core Container
  Spring的核心元件有3個:Core,Context和Bean。其中Bean是Spring的主角。在該模組當中,Spring提供了一個IoC容器的實現,用於我們以依賴注入的方式管理物件之間的依賴關係。
• (2)AOP
  Spring-AOP:基於代理的AOP支援。
• (3)資料訪問
  Spring-JDBC:提供以JDBC訪問資料庫的支援;
  Spring-TX:提供程式設計式和宣告式的事務支援;
  Spring-ORM:提供對物件/關係對映技術的支援;
  Spring-OXM:提供對物件/xml對映技術的支援;
  Spring-JMS:提供對JMS的支援。
• (4)Web
  Spring-Web:提供基礎的Web整合的功能,在Web專案中提供Spring的容器;
  Spring-Webmvc:提供基於Servlet的Spring MVC;
 Spring應用場景
 Spring發展到現在已經提供了大量的基於Spring的專案,主要有如下專案:

  Spring Boot :使用預設開發配置來實現快速開發;
  Spring Cloud:為分散式系統開發提供工具集;
  Spring Data:對主流的關係型和NoSQL資料庫的支援;
  Spring Batch:簡化及優化大量資料的批處理操作;
  Spring Security:通過認證和授權保護應用;
  Spring AMQP:對基於AMQP的訊息的支援;
  Spring Web Flow:基於Spring MVC提供基於嚮導流程式的Web應用開發。


本系列部落格主要總結Spring的IoC、AOP、事務管理、Spring MVC幾個方面的使用以及相關的原始碼分析。

二 、Spring-IoC入門

1 什麼是IoC(依賴注入)

IoC(Inversion of Control),通常被稱為控制反轉,也叫做依賴注入(DI)(當然這種說法是有爭議的,在此不去探究)。


Spring官網也給出了IoC容器的解釋:


何為控制反轉?舉個簡單的例子來說,
在面向物件的系統中,假如在論壇網站中有個評論的介面CommentService,在這個介面中要獲取評論數量,需要通過呼叫CommentDao 中的getCommentCount()方法來獲取。
我們的正常做法是在CommentService中先new CommentDao(),然後再呼叫CommentDao 中相關方法。
程式碼如下:

public class CommentDao {

    public int getCommentCount(){
        return 100;
    }
}

public class CommentService {

    private CommentDao commentDao;

    public int getCount(){
        commentDao = new CommentDao();
        return commentDao.getCommentCount();
    }
    public void setCommentDao(CommentDao commentDao) {
        this.commentDao = commentDao;
    }
}

 

而IoC的思想即是,在你需要依賴物件的時候,IoC容器即可提供一個已經例項化好的物件給你,這樣你就不需要自己去新建相應的依賴類。
下面將寫一個虛擬碼感受下IoC的過程(不是很嚴謹,感受下過程即可):

(1)首先將CommentDao,宣告為一個Bean(宣告為Bean後,IoC容器即會為其建立一個例項物件); 

<bean id = "commenDao" class="com.wgs.spring.demo1.CommentDao"/>

 

(2)再通過setter依賴注入的方式將CommentDao注入到CommentService當中

<bean id="commentService" class="com.wgs.spring.demo1.CommentService">
        <property name="commentDao">
            <ref bean="commentDao"></ref>
        </property>
</bean>

(3)當我們在CommentService需要用到CommentDao的時候,直接找IoC容器要到CommentDao的Bean即可。

IoContainer container = new ...;
CommentService service = (CommentService)container.getbean("commentService");
int result = service.getCount();

 所以,從上述例子可以看出:

通過使用IoC容器,物件依賴關係的管理被反轉了。 
即物件之間的相關依賴關係由IoC容器進行管理,並且由IoC完成物件的注入。

 

在面向物件系統中,物件封裝了資料和對資料的處理,物件的依賴關係常常體現在對資料和方法的依賴上,
而IoC模式是將這些依賴關係通過物件的依賴注入交給框架或IoC容器。

2 依賴注入的3種方式

(1)setter方法注入
上述過程即為setter注入的過程。當前物件只要為其依賴物件所對應的屬性新增setter方法,就可以通過setter方法將相應額依賴物件設定到當前物件中:

public class CommentService {

    private CommentDao commentDao;

    public int getCount(){
        commentDao = new CommentDao();
        return commentDao.getCommentCount();
    }

    public void setCommentDao(CommentDao commentDao) {
        this.commentDao = commentDao;
    }
}

 (2)構造方法注入 
即被注入物件可以通過在其構造方法中宣告依賴物件的引數列表,讓IoC容器知道其需要依賴那些物件。 
IoC容器會檢查被注入物件的構造方法,取得其需要的依賴物件的引數列表,進而為其注入對應的物件。物件構造完成後就能使用。

public class CommentService {

    private CommentDao commentDao;

    public int getCount(){
        commentDao = new CommentDao();
        return commentDao.getCommentCount();
    }

    public CommentService(CommentDao commentDao){
        this.commentDao = commentDao;
    }
}

 

(3)介面注入
不太常用,在此不介紹。

構造方法注入與setter方法注入對比:
(1)構造方法注入優點是物件在構造完成後即進入就緒狀態,可馬上使用;缺點是當依賴物件較多的時候,構造方法的引數列表會比較長;
(2)setter方法注入允許設定預設值,可以被繼承;
缺點是物件無法在構造完成後就馬上進入就緒狀態。