理解Spring:IOC的原理及手動實現

juejin.im/post/5c11b1e06fb9a04a0d56b787

導語

Spring是一個分層的JavaSE/EE full-stack(一站式) 輕量級開源框架。也是幾乎所有Java工作者必須要掌握的框架之一,其優秀的設計思想以及其代碼實現上的藝術也是我們需要掌握的。

要學習Spring,除了在我們的項目中使用之外,也需要對它的源碼進行研讀,但是Spring的實現涵蓋的知識很多,在加上其中的類的數量也是非常的多,在我們閱讀源碼時可能會在幾十個類之間穿插閱讀,很有可能一不小心就導致思維混亂。

有鑑於此,我這裡先對Spring中的幾個重要的模塊進行一個手動的簡易實現,一是熟悉這些模塊的原理,同時也是仿造Spring中的結構來對後面閱讀源碼打下基礎。

IOC(Inversion of Control)

Inversion of Control即控制反轉,其意思是將我們之前由客戶端代碼來創建的對象交由IOC容器來進行控制,對象的創建,初始化以及後面的管理都由IOC完成。

IOC的好處

解耦:IOC的出現解決了類與類之間的耦合,我們在Web開發的Servlet時代,如果一個Servlet需要依賴另一個類的某些實現,那麼我們需要在當前類對依賴的類進行創建和初始化,如果其他類也依賴了這個類,那也需要進行創建和初始化,而交給了IOC來管理的話,那麼在需要的時候只需向IOC進行申請,而不需要重複的創建和初始化。當然,IOC也允許每次都重新創建一個新的對象。

方便與AOP進行配合:AOP也是一個使用十分頻繁的功能,通過IOC可以十分方便的與AOP進行配合。

IOC中設計的設計模式

工廠模式。IOC容器來負責創建管理類實例對象,在需要時向IOC進行申請,從IOC中獲取。所以IOC容器也稱為bean工廠。

工廠模式是一種比較簡單易懂的設計模式,這裡就不在介紹了,如果有需要的可以看看工廠模式。

IOC的手動實現

Bean定義

IOC的主要的功能便是對Bean進行管理,包括創建、初始化、管理以及銷燬的工作。首先我們面對的問題就是我們怎麼讓IOC能夠創建一個Bean?為了創建Bean我們需要提供一些什麼?

如何創建Bean

在不手動通過new關鍵字創建的情況下創建類實例的對象方法有兩種:

  • 反射:通過反射的方法可以創建類的實例:clazz.getClass().newInstance();。
  • 工廠模式:工廠模式可以讓我們在不接觸實例類的情況下創建出實例。
<code>publicclassPersonFactory{
publicPersongetPerson(){
returnnewPerson();
}
}
/<code>

為了創建Bean我們需要提供什麼

通過分析上面的兩種方法可以輕鬆得出答案。

對於反射的方式我們僅需提供實例的Class對象。

對於工廠方法我們需要提供的就是創建該類的工廠名(factoryName)和方法名(methodName);

除了創建bean還需要做些什麼

IOC容器是對bean的整個生命週期進行管理,除了創建之外還需要對bean進行初始化,以及不需要時對bean進行銷燬的工作(如釋放資源等)。所以我們還需要提供初始化和銷燬等操作。

到這裡創建bean需要的基本分析完了,看類圖:

理解Spring:IOC的原理及手動實現

Bean工廠

Bean的定義解決了,但是這個bean定義以及創建好的Bean實例放在哪裡呢,我們需要一個統一的地方來存放這些東西以方便我們要用的時候方便取。

我們定義一個Bean工廠來存放bean,在需要的時候從bean工廠中取即可,bean工廠對外提供的也僅僅是一個獲取bean的方法即可,由於bean的類型不定,所以返回值定位Object。

理解Spring:IOC的原理及手動實現

註冊Bean定義

到了現在我們有了創建bean的Bean定義,有了存放和管理bean的Bean工廠,現在需要考慮的是怎麼來聯繫這兩個類,我們還需要另外一個接口,接口的功能是讓我們能註冊和獲取bean定義,這裡我們通過beanName來區分不同的bean。

理解Spring:IOC的原理及手動實現

代碼實現

到這裡我們實現一個簡易的IOC容器的需要的東西基本準備完成了,看下基本類圖:

理解Spring:IOC的原理及手動實現

基本代碼實現:

DefaultBeanDefinition:

<code>publicclassDefaultBeanDefinitionimplementsBeanDefinition{

privateClass>clazz;

privateStringbeanFactoryName;

privateStringcreateBeanMethodName;

privateStringstaticCreateBeanMethodName;

privateStringbeanInitMethodName;

privateStringbeanDestoryMethodName;


privatebooleanisSingleton;

//setter


publicvoidsetSingleton(booleansingleton){
isSingleton=singleton;
}

@Override
publicClass>getBeanClass(){
returnthis.clazz;
}

@Override
publicStringgetBeanFactory(){
returnthis.beanFactoryName;
}

@Override
publicStringgetCreateBeanMethod(){
returnthis.createBeanMethodName;
}

@Override
publicStringgetStaticCreateBeanMethod(){
returnthis.staticCreateBeanMethodName;
}

@Override
publicStringgetBeanInitMethodName(){
returnthis.beanInitMethodName;
}

@Override
publicStringgetBeanDestoryMethodName(){
returnthis.beanDestoryMethodName;
}

@Override
publicStringgetScope(){
returnthis.isSingleton?BeanDefinition.SINGLETION:BeanDefinition.PROTOTYPE;
}

@Override
publicbooleanisSingleton(){
returnthis.isSingleton;
}

@Override
publicbooleanisPrototype(){
return!this.isSingleton;
}
}
/<code>

DefaultBeanFactory:


理解Spring:IOC的原理及手動實現


理解Spring:IOC的原理及手動實現


理解Spring:IOC的原理及手動實現


理解Spring:IOC的原理及手動實現


理解Spring:IOC的原理及手動實現

簡單測試一下:實例bean:

<code>publicclassUser{

privateStringname;

privateintage;

//gettersetter

publicvoidinit(){
System.out.println("init...");
}

publicvoiddestory(){
System.out.println("destory...");
}

}
/<code>

工廠類:

<code>publicclassTestFactory{
publicObjectcreateMethod(){
returnnewUser();
}

publicstaticObjectstaticCreateMethod(){
returnnewUser();
}
}
/<code>

測試類:


理解Spring:IOC的原理及手動實現

小結

一個簡易的容器就這樣實現了,當然我們這裡只是具備了基本的功能,實際上還差的遠,比如帶參數的bean的實例化等功能。但是IOC的基本原理已經表達出來了,後面我們只需在這個基礎上添加新的功能即可。


分享到:


相關文章: