<深入理解Abp> 程序启动 - 一切的开始
我们知道net core
应用程序的核心配置在项目中的startup.cs
文件.
public class startup { public iserviceprovider configureservices(iservicecollection services) { //... return services.addabp<webmodule>(//...); } public void configure(iapplicationbuilder app) { app.useabp(//...); //... } }
-
public void configureservices(iservicecollection services)
方法主要用于将服务添加到di
容器中并做一些配置. -
public void configure(iapplicationbuilder app)
配置请求管道.
abp
框架使用自己的di容器(主要为了兼容之前的net framework版本和使用一些高级特性,如拦截器),所以我们在configureservices
方法的底部会看到return services.addabp(//...)
这时候configureservices
的方法返回值也变成了iserviceprovider
(关于这点请参考:)
框架与aspnet core
深度集成的地方就在addabp
方法和useabp
的内部:
public static class abpservicecollectionextensions { /// <summary> /// integrates abp to aspnet core. /// </summary> /// <typeparam name="tstartupmodule">startup module of the application which depends on other used modules. should be derived from <see cref="abpmodule"/>.</typeparam> /// <param name="services">services.</param> /// <param name="optionsaction">an action to get/modify options</param> public static iserviceprovider addabp<tstartupmodule>(this iservicecollection services, [canbenull] action<abpbootstrapperoptions> optionsaction = null) where tstartupmodule : abpmodule { var abpbootstrapper = addabpbootstrapper<tstartupmodule>(services, optionsaction); configureaspnetcore(services, abpbootstrapper.iocmanager); return windsorregistrationhelper.createserviceprovider(abpbootstrapper.iocmanager.ioccontainer, services); } private static void configureaspnetcore(iservicecollection services, iiocresolver iocresolver) { //see https://github.com/aspnet/mvc/issues/3936 to know why we added these services. services.tryaddsingleton<ihttpcontextaccessor, httpcontextaccessor>(); services.tryaddsingleton<iactioncontextaccessor, actioncontextaccessor>(); //use di to create controllers services.replace(servicedescriptor.transient<icontrolleractivator, servicebasedcontrolleractivator>()); //use di to create view components services.replace(servicedescriptor.singleton<iviewcomponentactivator, servicebasedviewcomponentactivator>()); //change anti forgery filters (to work proper with non-browser clients) services.replace(servicedescriptor.transient<autovalidateantiforgerytokenauthorizationfilter, abpautovalidateantiforgerytokenauthorizationfilter>()); services.replace(servicedescriptor.transient<validateantiforgerytokenauthorizationfilter, abpvalidateantiforgerytokenauthorizationfilter>()); //add feature providers var partmanager = services.getsingletonserviceornull<applicationpartmanager>(); partmanager?.featureproviders.add(new abpappservicecontrollerfeatureprovider(iocresolver)); //configure json serializer services.configure<mvcjsonoptions>(jsonoptions => { jsonoptions.serializersettings.contractresolver = new abpmvccontractresolver(iocresolver) { namingstrategy = new camelcasenamingstrategy() }; }); //configure mvc services.configure<mvcoptions>(mvcoptions => { mvcoptions.addabp(services); }); //configure razor services.insert(0, servicedescriptor.singleton<iconfigureoptions<razorviewengineoptions>>( new configureoptions<razorviewengineoptions>( (options) => { options.fileproviders.add(new embeddedresourceviewfileprovider(iocresolver)); } ) ) ); } private static abpbootstrapper addabpbootstrapper<tstartupmodule>(iservicecollection services, action<abpbootstrapperoptions> optionsaction) where tstartupmodule : abpmodule { var abpbootstrapper = abpbootstrapper.create<tstartupmodule>(optionsaction); services.addsingleton(abpbootstrapper); return abpbootstrapper; } }
abpbootstrapper
作为abp
核心的引导类,负责初始化abp
系统,加载插件,配置abp
和模块以及启动模块(preinitialize
,initialize
, postinitialize
). 这个引导类在console应用程序中同样可以启动abp
系统.
接下来abp
配置和替换了多个mvc
的组件,如icontrolleractivator,iviewcomponentactivator,mvcjsonoptions,mvcoptions
更多的配置在mvcoptions.addabp(services)
方法下:
internal static class { public static void addabp(this mvcoptions options, iservicecollection services) { addconventions(options, services); addfilters(options); addmodelbinders(options); } private static void addconventions(mvcoptions options, iservicecollection services) { options.conventions.add(new abpappserviceconvention(services)); } private static void addfilters(mvcoptions options) { options.filters.addservice(typeof(abpauthorizationfilter)); options.filters.addservice(typeof(abpauditactionfilter)); options.filters.addservice(typeof(abpvalidationactionfilter)); options.filters.addservice(typeof(abpuowactionfilter)); options.filters.addservice(typeof(abpexceptionfilter)); options.filters.addservice(typeof(abpresultfilter)); } private static void addmodelbinders(mvcoptions options) { options.modelbinderproviders.insert(0, new abpdatetimemodelbinderprovider()); } }
abpappserviceconvention
主要用于配置动态api,这个后面会有一章单独说明.
abpauthorizationfilter abpauditactionfilter abpvalidationactionfilter abpuowactionfilter abpexceptionfilter abpresultfilter
依次添加6个mvc
过滤器分别实现授权,审计,参数验证,工作单元,异常处理以及返回内容的包装.(请注意过滤器顺序很重要)
abpdatetimemodelbinderprovider
用作datetime
的统一时区处理.
接下来我们再看useabp
方法:
public static class abpapplicationbuilderextensions { public static void useabp(this iapplicationbuilder app) { app.useabp(null); } public static void useabp([notnull] this iapplicationbuilder app, action<abpapplicationbuilderoptions> optionsaction) { check.notnull(app, nameof(app)); var options = new abpapplicationbuilderoptions(); optionsaction?.invoke(options); if (options.usecastleloggerfactory) { app.usecastleloggerfactory(); } initializeabp(app); if (options.useabprequestlocalization) { //todo: this should be added later than authorization middleware! app.useabprequestlocalization(); } if (options.usesecurityheaders) { app.useabpsecurityheaders(); } } public static void useembeddedfiles(this iapplicationbuilder app) { app.usestaticfiles( new staticfileoptions { fileprovider = new embeddedresourcefileprovider( app.applicationservices.getrequiredservice<iiocresolver>() ) } ); } private static void initializeabp(iapplicationbuilder app) { var abpbootstrapper = app.applicationservices.getrequiredservice<abpbootstrapper>(); abpbootstrapper.initialize(); var applicationlifetime = app.applicationservices.getservice<iapplicationlifetime>(); applicationlifetime.applicationstopping.register(() => abpbootstrapper.dispose()); } public static void usecastleloggerfactory(this iapplicationbuilder app) { var castleloggerfactory = app.applicationservices.getservice<castle.core.logging.iloggerfactory>(); if (castleloggerfactory == null) { return; } app.applicationservices .getrequiredservice<iloggerfactory>() .addcastlelogger(castleloggerfactory); } public static void useabprequestlocalization(this iapplicationbuilder app, action<requestlocalizationoptions> optionsaction = null) { var iocresolver = app.applicationservices.getrequiredservice<iiocresolver>(); using (var languagemanager = iocresolver.resolveasdisposable<ilanguagemanager>()) { var supportedcultures = languagemanager.object .getlanguages() .select(l => cultureinfo.getcultureinfo(l.name)) .toarray(); var options = new requestlocalizationoptions { supportedcultures = supportedcultures, supporteduicultures = supportedcultures }; var userprovider = new abpuserrequestcultureprovider(); //0: querystringrequestcultureprovider options.requestcultureproviders.insert(1, userprovider); options.requestcultureproviders.insert(2, new abplocalizationheaderrequestcultureprovider()); //3: cookierequestcultureprovider options.requestcultureproviders.insert(4, new abpdefaultrequestcultureprovider()); //5: acceptlanguageheaderrequestcultureprovider optionsaction?.invoke(options); userprovider.cookieprovider = options.requestcultureproviders.oftype<cookierequestcultureprovider>().firstordefault(); userprovider.headerprovider = options.requestcultureproviders.oftype<abplocalizationheaderrequestcultureprovider>().firstordefault(); app.userequestlocalization(options); } } public static void useabpsecurityheaders(this iapplicationbuilder app) { app.usemiddleware<abpsecurityheadersmiddleware>(); } }
核心initializeabp(app)
,使用上文之前提到abpbootstrapper
引导启动abp
系统.(我们知道abp模块有个shutdown()
方法,abp
使用iapplicationlifetime
接口捕获应用程序事件实现模块的shoutdown
)
之后按需启动几个中间件,如: requestlocalization
,securityheaders
等(这些小组件和之前的过滤器后面我会分别详细介绍,这里就不深入讲解)
至此abp
已经把框架的相关组件集成到了mvc
中.接下来程序启动.请求被各种中间件处理(mvc中间件会调用过滤器).
abp中文网:
abp交流群:735901849(纯技术交流,无广告,不卖课)
上一篇: 数据库实验九
下一篇: mysql中简单增删改查语句语法