關於Spring的一些想法

Spring是容器還是工廠

使用過Spring的同學都知道,“Spring是一個容器”。其實,這種說法不太準確,Spring提供的容器不止一種,例如有ClasspathXmlApplicationContext、XmlWebApplicationContext等多種容器,所有這些容器的父類都是BeanFactory。但是爲什麼起名叫"工廠"呢?單純的"容器"只起到一個存放對象的作用,如果只是想把對象存放起來,那麼ArrayList,HashSet等Java集合類完全可以勝任,根本用不着Spring。Spring容器並不是單純用於存放對象的,它存放對象定義(bean definition),而不止是存放對象(bean)。當需要一個對象時,我們從bean容器獲取,而bean容器(BeanFactory)負責根據定義創建對象,所以說它是一個"工廠"。
反過來,它又爲什麼叫做"容器"?這是因爲在大多數時候,bean都被定義爲單例(singleton,與GoF中的singleton略有不同),且這些bean的類是Spring提供的ClassLoader加載的,單例的bean被實例化一次之後就一直保存在這個工廠中,以後每次請求獲得這個bean都是同一個對象,相當於這個對象被放在BeanFactory中了,所以它又可以視爲一個容器。
而對於非singleton的bean來說,例如scope等於prototype的bean,BeanFactory就主要表現爲一個工廠了,每次請求都返回一個不同的實例。既然說到scope,順便分享一道常見的Spring面試題,“Spring中bean/對象的類型(scope)有哪些”?回答:取決於你所使用的具體容器。如果使用的是基本容器,例如ClasspathXmlApplicationContext,那麼只有singleton和prototype可用;如果使用的是Web容器(例如WebXmlApplicationContext),那麼就有singleton, prototype,request,session和global等可用;另外,scope還可以自定義。Spring通過把自己設計成一個管理應用程序模塊定義的容器以及工廠,而不是管理模塊自身的容器,讓模塊可以分別獨立開發,實現了模塊之間的解耦。

深入理解Dependency Injection和Inversion of Control

依賴注入(Depdendency Injection)和控制反轉(IoC,Inversion of Control)是同一個概念,Spring實踐了這個思想,爲Java Web應用程序建立起一個基本框架。換句話說,Spring是Java Web應用程序的基本框架。下次面試官如果問你,“爲什麼要使用Spring”,你可以回答"它提供了一個Web應用程序的基本框架",然後說它是工廠和容器,提供了IoC,不要回答"用起來方便"。因爲任何一個大型應用程序都包含很多組件(components),組件之間互相調用,並且在運行時並非所有組件都必須創建。如果沒有一個整體的結構(框架),程序將會變得混亂、難以維護。假如不使用Spring,那麼每次需要調用另一個組件的時候就new一個對象,或者getInstance得到一個實例。當組件越來越多,程序規模越來越大,這種方式會讓組件之間的耦合度很高,難以維護。Spring框架基於BeanFactory,把模塊的配置信息(bean definition)統一管理起來(有的模塊可以根據需要創建,若不調用則不創建),同時,還把模塊的配置參數也統一管理(每個模塊不必自己讀配置參數,由Spring加載)。程序結構變清晰很多。在此基礎上,加上依賴注入的功能,即Spring負責把模塊依賴的其他模塊推送(push)進來,而不是模塊自己去拉取(pull),所以是一個"反轉(IoC)",進一步簡化了大型應用程序開發。根據上面討論,我們總結一下,爲什麼要使用Spring:Spring提供一個容器/工廠,統一管理模塊的定義,根據需要創建。把模塊的配置參數統一管理,模塊不需要自行讀取配置。Spring提供依賴注入,把依賴的模塊自動推送進來,不需要模塊自己拉取。此外,Spring提供了對很多其他第三方框架的集成功能,減少了樣板代碼(boilerplate)。

Spring中bean的生命週期

在Web應用程序啓動過程中,Spring容器中的每個bean也有各自的初始化順序。一個bean,從bean definition被加載到初始化完成,按照以下順序執行:1. BeanFactory加載完bean definition和class,實例化除了bean對象。2. 檢查有沒有實現BeanNameAware,有則調用setBeanName(得到bean id)3. 檢查有沒有實現BeanClassLoaderAware,有則調用setBeanClassLoader。4. 檢查有沒有實現EnvironmentAware,有則調用setEnvironment。5. 檢查有沒有實現EmbeddedValueResolverAware,有則調用setEmbeddedValueResolver。6. 檢查有沒有實現ResourceLoaderAware,有則調用setResourceLoader。7. 檢查有沒有實現ApplicationEventPublisherAware,有則調用setApplicationEventPublisher。8. 檢查有沒有實現MessageSourceAware,有則調用setMessageSource。9. 檢查有沒有實現ApplicationContextAware,有則調用setApplicationContext。10. 檢查有沒有實現ServletContextAware,有則調用setServletContext。11. 調用BeanPostProcessors中的所有postProcessBeforeInitialization,對bean進行一些更進一步的配置。12. 調用InitializingBean接口中的afterPropertiesSet執行bean自身提供的初始化代碼。13. 調用通過其他方式指定的init-method方法,執行bean自身的初始化。14. 調用BeanPostProcessors中的所有postProcessAfterInitialization方法。經歷了上述的14個步驟,spring bean才完整地創建出來,很不容易。從以上步驟可以瞭解到,在初始化方法中哪些資源是已經準備好可以訪問的,哪些是還不能訪問的。

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