何為請求限流? 請求限流是一種控制API或其他Web服務的流量的技術。它的目的是限制客戶端對伺服器發出的請求的數量或速率,以防止伺服器過載或響應時間變慢,從而提高系統的可用性和穩定性。 中小型項目請求限流的需求 按IP、用戶、全局限流 基於不同實現的限流設計(基於Redis或者LRU緩存) 基於註解 ...
1、IoC的理念
IoC全稱為Inversion of Control,中文翻譯為控制反轉,同時還有一個別名叫 依賴註入DI(Dependency Injection)。大多將IoC與DI看作同等概念,也有部分觀點認為 依賴註入可以看作IoC的一種實現方式。
在沒有Spring的時候,當我們需要依賴某個類或服務時,一般通過new創建一個對象(或者通過ServiceLocator解決直接的依賴耦合),這些都需要主動的去獲取需要的對象。
ServiceLocator是通過引入中間代理者消除對象間複雜的耦合關係,並統一管理分散的複雜耦合關係。
IoC的出現就為我們提供了更加簡潔的方式,不用主動去構造對象,將“主動獲取”轉變為“被動接收”,下圖即為IoC在整個過程中的所承擔的角色
通常情況下,被註入對象會直接依賴於被依賴對象。但是在IoC的場景中,二者通過IoC Service Provider來交互,全部由IoC Service Provider統一管理。控制權由被註入對象轉變為了IoC Service Provider 那裡。
public class NewsProvider {
// NewsProvider 為被註入對象
// INewsListener和INewsPersister為被依賴對象
private INewsListener newsListener;
private INewsPersister newsPersister;
}
其實IoC就是這麼簡單!以前是需要什麼自己去拿,現在是需要什麼東西別人主動送過來。下圖形象的說明瞭使用IoC模式的前後差別
2、IoC(DI)的幾種依賴註入的方式
IoC模式最常用的有三種依賴註入方式,分別是構造方法註入(Constructor Injection)、setter方法註入(Setter Injection)以及介面註入(Interface Injection)。
2.1、構造方法註入
構造方法註入即 被註入對象可以通過在其構造方法中聲明所依賴對象的參數列表,讓IoC容器知道它所需要的依賴對象列表。由於同一個對象是不可能是被構造兩次的,因此,被註入對象的構造乃至其整個生命周期,都是由IoC Service Provider來管理的。
IoC Service Provider會檢查被註入對象的構造方法,取得它所需要的依賴對象列表,進而為其註入相應的對象。具體代碼示例如下
public class NewsProvider {
// NewsProvider 為被註入對象
// INewsListener和INewsPersister為被依賴對象
private INewsListener newsListener;
private INewsPersister newsPersister;
public NewsProvider(INewsListener newsListener, INewsPersister newsPersister) {
this.newsListener = newsListener;
this.newsPersister = newsPersister;
}
}
構造方法註入的方式比較直觀,對象被構造完成後,就進入了就緒裝填,可以馬上使用。
2.2、setter方法註入
對於JavaBean對象來說,通常會通過setter方法來更改相應的對象屬性。所以,當前對象只要為其依賴對象所對應的屬性添加setter方法,就可以通過setter方法將相應的依賴對象設置到被註入對象中。代碼示例如下
public class NewsProvider {
// NewsProvider 為被註入對象
// INewsListener和INewsPersister為被依賴對象
private INewsListener newsListener;
private INewsPersister newsPersister;
public void setNewsListener(INewsListener newsListener) {
this.newsListener = newsListener;
}
public void setNewsPersister(INewsPersister newsPersister) {
this.newsPersister = newsPersister;
}
}
這樣,外界就可以通過調用setNewsListener和setNewsPersister方法來註入依賴對象了。
需要註意的是,setter方法註入不像構造方法註入那樣,對象構造完成後即可使用,相對而言更加寬鬆一些,可以在對象構造完成之後再註入。
2.3、介面註入(基本廢棄)
相對前面的兩種註入方式來說,介面註入會更加複雜。被註入對象如果想讓IoC Service Provider為其註入依賴對象,就必須實現某個介面。這個介面提供一個方法,用來為其註入依賴對象。IoC Service Provider 最終會通過這些介面來獲取被註入對象所需要的依賴對象列表。
NewsProvicer為了讓IoC Service Provider 為其註入所依賴的NewsListener對象,首先需要實現一個介面 INewsListenerCallable(名稱隨意),這個介面會聲明一個injectNewsListener方法(名稱隨意),重要的是該方法的參數,必須是所依賴對象的類型。這樣,對應的IoC Service Provider 就可以通過這個介面方法將依賴對象註入到 被註入對象 NewsProvider 當中。代碼示例如下。
public interface NewsListenerCallable {
// 聲明方法
void injectNewsListener(INewsListener newsListener);
}
public class NewsProvider implements NewsListenerCallable{
private INewsListener newsListener;
@Override
public void injectNewsListener(INewsListener newsListener) {
this.newsListener = newsListener;
}
}
2.3、三種註入方式的比較
- 構造方法註入。這種註入方式的優點就是,對象在構造完成之後,就已進入就緒狀態,可以馬上使用。缺點就是,當依賴對象變多時,構造方法的參數列表會比較長。同時通過反射構造對象時,對相同類型的參數處理會比較困難,維護和使用上也比較麻煩。而且在Java中,構造方法無法被繼承,無法設置預設值。對於非必須的依賴處理,可能還需要引入多個構造方法,維護不便。
- setter方法註入。優點就是,在描述性上會比構造方法註入要好,同時可以被繼承,允許設置預設值,而且有良好的IDE支持。缺點就是對象無法在構造完成後立馬進入就緒狀態。
- 介面註入。從註入方式的使用上來說,介面註入是目前不提倡的一種方法,基本處於“退役狀態”。因為需要被註入對象實現不必要的介面,帶有侵入性。
綜上,構造方法註入和setter註入因為其侵入性較弱,且易於理解和使用,所以是現在使用最多的註入方式;而介面註入由於其侵入性,已經不流行了。
本文由博客一文多發平臺 OpenWrite 發佈!