Abp是一種基於模塊化設計的思想構建的。開發人員可以將自定義的功能以模塊(module)的形式集成到ABP中。具體的功能都可以設計成一個單獨的Module。Abp底層框架提供便捷的方法集成每個Module.下圖是所有Abp自帶的module.AbpModule是所有Module的基類,其已經擁有了IIocManager和IAbpStartupConfiguration的受保護的成員,從其派生的Module都可以直接獲取並使用相關的功能(依賴注入,Configuration)。:
以下以AbpWebMvcModule為例,這個就是Abp自定義的一個模塊,該模塊繼承自AbpModule。 那么這個模塊是怎么和Abp底層框架集成到一塊的呢?
所謂集成可以從兩個角度開看:
第一,Abp底層框架是如何發現這個Module的?
第二,這個Module是如何把自己的組件(類,接口)注冊到Abp底層框架中(AbpWebMvcModule中,這問題就演變為如何把Controller注冊到Abp底層框架的容器中)?
先分析第二個問題: 如下代碼中AbpWebMvcModule類中的PreInitialize 和 Initialize 很好的回答了這個問題。在PreInitialize中Abp調用IocManager的AddConventionalRegistrar方法以實例化的ControllerConventionalRegistrar為參數。上一篇已介紹過ControllerConventionalRegistrar的用處,這個類的實例在執行RejisterAssembly時會是將繼承至controller的類型都注入到Abp底層框架中(也就是Castle容器中)。 Initialize這注冊了一個Castle的WindsorControllerFactory以替換MVC下默認的ControllerFactory,這樣ASP.NET MVC將使用WindsorControllerFactory從Castle容器中解析出controller.
AddConventionalRegistrar方法向IocManager的一個私有泛型集合List<IConventionalDependencyRegistrar>注冊注冊機制,通常所有的Module類的預初始化方法中調用以決定哪些類型需要被注冊(如果沒有就無需調用)
現在在看回第一個問題:Abp底層框架是如何發現這個Module的?
解釋這個問題前,有必要解釋一下Module的描述信息是如何被封裝的。AbpModuleInfo用於封裝AbpModule的基本信息。 AbpModuleCollection則是AbpModuleInfo的集合。
Abp底層框架發現Module是從AbpBootstrapper在執行Initialize方法的時候開始的,該方法會調用IAbpModuleManager實例的InitializeModules方法,這個方法接着調用DefaultModuleFinder的FindAll方法(該方法用於過濾出AbpModule的assembly),而FindAll方法調用TypeFinder得到所有的assembly. 所以只要你定義的assembly中有一個繼承至AbpModule的類,並且該assembly被引用到你的項目中,那么這個Module就可以說會被Abp底層框架集成了。
具體關系如下圖。
AbpModuleManager得到所有的AbpModule的AbpModuleInfo以后,逐個調用這些Module的PreInitialize,Initialize和PostInitialize以完成初始化。(注意,ABP先完成所有Module的PreInitialize,接着再執行所有Module的Initialize,最后執行PostInitialize。不是執行完一個Module的這三個方法,再去執行下一個Module的這三個方法。這個很好理解,如果是后者的話,我們只要一個Initialize方法就可以了,所有的方法都放入這個Initialize方法中即可。)至此,AbpWebMvcModule算是完成了和Abp底層框架的集成了。值得一提的是所有AbpModule的關閉銷毀也是通過AbpModuleManager調用ShutdownModules來遍歷執行AbpModule的Shutdown來實現的。
上面解釋了關於自定義的模塊的注冊和初始化,那么Abp底層框架的一些功能模塊的類型的注冊如何實現的呢? 通過AbpKernelModule來實現的,該類會調用如下圖中的各種Register完成初始化(攔截器的注入)。以后的文章會逐個解釋這些功能模塊。