[Abp vNext 源码分析] - 1. 框架启动流程分析

一、简要说明

本篇文章主要剖析与讲解 Abp vNext 在 Web API 项目下的启动流程,让大家了解整个 Abp vNext 框架是如何运作的。总的来说 ,Abp vNext 比起 ABP 框架更加精简。因为在 vNext 版本当中,原来归属于 Abp 库的许多内置的基本组件 (组织单元、拦截器等) 被拆分成了单独的模块,这样我们来看它整个启动流程就更加地直观清晰。

二、源码分析

要分析其源码,我这里是从他官方的 Demo 模板入手的,你可以在 https://abp.io 上构建你自己的模板项目。工具上我使用的是 Jetbrains 家的 Rider,配置好符号服务器(External Symbols Server),我们就能够直接调试其底层源码。(因为 Abp vNext 项目使用了 Source Link)

2.1 Startup 文件的入口点

这里我选择的项目是 Web API,直接来到其 Startup.cs 文件,我们就可以看到在 Startup 类当中的 Configure() 与 ConfigureService() 方法内部我们注入并启用了 Abp vNext 框架。

public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
{

services.AddApplication<DemoAppModule>(options =>
{
options.UseAutofac();
});


return services.BuildServiceProviderFromFactory();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{

app.InitializeApplication();
}
}

在上面我们可以看到,ABP vNext 在注入服务的时候支持传入一个 Action<AbpApplicationCreationOptions> 委托。上述代码中,这个委托内部使用了 UseAutoFac() 将 AutoFac 的容器注入到了 MS IoC 当中,关于这块代码下文会着重讲解。

2.2 Abp 服务注册

在上一节看到的服务注册代码,是通过扩展 IServiceCollection 接口编写的一个扩展方法实现的,在方法内部是通过 AbpApplicationFactory 静态工厂来创建一个 AbpApplicationBase 实例。

public static class ServiceCollectionApplicationExtensions
{
public static IAbpApplicationWithExternalServiceProvider AddApplication<TStartupModule>(
[NotNull] this IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
where TStartupModule : IAbpModule
{
return AbpApplicationFactory.Create<TStartupModule>(services, optionsAction);
}


}

在这个方法当中,通过名字 WithExternalServiceProvider 我们就知道,这个 Applictaion 是依赖于外部的 IServiceProvider 实例。

提示:

它继承的 AbpApplicationBase 基类还拥有另外一个实现,即 AbpApplicationWithInternalServiceProvider 类型,该类型一般 用于控制台程序,它会在 Abp vNext 框架内自行构建一个 IServiceProvider 对象。

我们回到之前的代码,在这个 AbpApplicationWithExternalServiceProvider 类型内部的构造方法很简单,只是通过 IServiceCollection 对象把自己注入到了服务集合当中。

internal class AbpApplicationWithExternalServiceProvider : AbpApplicationBase, IAbpApplicationWithExternalServiceProvider
{
public AbpApplicationWithExternalServiceProvider(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction
) : base(
startupModuleType,
services,
optionsAction
)
{

services.AddSingleton<IAbpApplicationWithExternalServiceProvider>(this);
}


public void Initialize(IServiceProvider serviceProvider)
{
Check.NotNull(serviceProvider, nameof(serviceProvider));

SetServiceProvider(serviceProvider);

InitializeModules();
}
}

重点代码在于它的基类构造函数,在基类构造函数当中 Abp vNext 注入了诸多 ASP.NET Core 需要的日志服务、本地化服务等。并且它也抽象出了一个 IModuleLoader,用于辅助我们加载模块。

internal AbpApplicationBase(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction
)
{
Check.NotNull(startupModuleType, nameof(startupModuleType));
Check.NotNull(services, nameof(services));


StartupModuleType = startupModuleType;
Services = services;


services.TryAddObjectAccessor<IServiceProvider>();


var options = new AbpApplicationCreationOptions(services);
optionsAction?.Invoke(options);


services.AddSingleton<IAbpApplication>(this);
services.AddSingleton<IModuleContainer>(this);


services.AddCoreServices();

services.AddCoreAbpServices(this, options);


Modules = LoadModules(services, options);
}

提示:

这里的对象访问器其实就是一个占位的类型对象,这样方面后面替换其具体实现。例如在上文当中的 IServiceProvider 通过 ObjectAccessor<T> 对象包裹起来,其值是 NULL,但是在后面我们可以根据自己的需要替换其具体的 Value 。

2.3 替换 IoC 容器

再回到之前调用 AddApplication<T>() 传递的委托方法,在其内部我们调用了 UseAutofac() 方法。这个方法很简单,内部就只有三行代码。

这三行代码主要是初始化了一个 AutoFac 的容器构建对象,其次注入 IServiceProviderFactory 和 Abp 的默认实现 AbpAutofacServiceProviderFactory

public static void UseAutofac(this AbpApplicationCreationOptions options)
{
var builder = new ContainerBuilder();
options.Services.AddObjectAccessor(builder);

options.Services.AddSingleton((IServiceProviderFactory<ContainerBuilder>) new AbpAutofacServiceProviderFactory(builder));
}

这个工厂类的就是在构建 IServiceProvider 的时候使用,即 BuildServiceProviderFromFactory() 方法。该方法内部逻辑很简单,就是从已经注册的服务集合(IServiceCollection)当中获得之前注册的工厂类,通过调用工厂类的 CreateServiceProvider()方法构建 IServiceProvider,并作为返回值替换掉默认的 IoC 容器。

public static IServiceProvider BuildServiceProviderFromFactory([NotNull] this IServiceCollection services)
{
Check.NotNull(services, nameof(services));


foreach (var service in services)
{
var factoryInterface = service.ImplementationInstance?.GetType()
.GetTypeInfo()
.GetInterfaces()
.FirstOrDefault(i => i.GetTypeInfo().IsGenericType &&
i.GetGenericTypeDefinition() == typeof(IServiceProviderFactory<>));

if (factoryInterface == null)
{
continue;
}


var containerBuilderType = factoryInterface.GenericTypeArguments[0];
return (IServiceProvider)typeof(ServiceCollectionCommonExtensions)
.GetTypeInfo()
.GetMethods()
.Single(m => m.Name == nameof(BuildServiceProviderFromFactory) && m.IsGenericMethod)
.MakeGenericMethod(containerBuilderType)
.Invoke(null, new object[] { services, null });
}

return services.BuildServiceProvider();
}


public static IServiceProvider BuildServiceProviderFromFactory<TContainerBuilder>([NotNull] this IServiceCollection services, Action<TContainerBuilder> builderAction = null)
{
Check.NotNull(services, nameof(services));

var serviceProviderFactory = services.GetSingletonInstanceOrNull<IServiceProviderFactory<TContainerBuilder>>();
if (serviceProviderFactory == null)
{
throw new AbpException($"Could not find {typeof(IServiceProviderFactory<TContainerBuilder>).FullName} in {services}.");
}

var builder = serviceProviderFactory.CreateBuilder(services);
builderAction?.Invoke(builder);
return serviceProviderFactory.CreateServiceProvider(builder);
}

2.3 初始化 Abp 框架

这里针对 IApplicationBuilder 的扩展是在模块包 Volo.Abp.AspNetCore 当中的,这里仅讲解 ASP.NET Core Mvc 项目是如何处理的。

public static void InitializeApplication([NotNull] this IApplicationBuilder app)
{
Check.NotNull(app, nameof(app));


app.ApplicationServices.GetRequiredService<ObjectAccessor<IApplicationBuilder>>().Value = app;


app.ApplicationServices.GetRequiredService<IAbpApplicationWithExternalServiceProvider>().Initialize(app.ApplicationServices);
}

这里可能会疑惑 ObjectAccessor<IApplicationBuilder> 是在什么时候注入的,其实该类型是在 AbpAspNetCoreModule 模块注册的。

public class AbpAspNetCoreModule : AbpModule
{

public override void ConfigureServices(ServiceConfigurationContext context)
{

context.Services.AddObjectAccessor<IApplicationBuilder>();
}

}

接着看初始化方法内部的操作,初始化方法定义是在基类当中,方法名是 InitializeModules() ,在方法内部,通过 IModuleManager 来执行模块的初始化方法。

protected virtual void InitializeModules()
{
using (var scope = ServiceProvider.CreateScope())
{
scope.ServiceProvider
.GetRequiredService<IModuleManager>()
.InitializeModules(new ApplicationInitializationContext(scope.ServiceProvider));
}
}

除了模块的初始化,模块的销毁动作 Abp vNext 好像是没有作处理,你可以挂载 IApplicationLifetime.ApplicationStopping 事件来手动执行模块的销毁方法。

三、总结

总体来说 Abp vNext 的启动流程与之前精简了许多,这是因为在新的框架当中将许多基础组件从核心层移除了,用户可以自由选择自己需要加载的组件。IoC 相关的代码则是通过的 Microsoft Dependency 提供的 IServiceProvider/IServiceCollection 进行操作,没有了之前的 IocManager

原文地址:https://www.cnblogs.com/myzony/p/10722480.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 
640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316247.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 MSIX 打包 DotNetCore 3.0 客户端程序

如何你希望你的 WPF 程序能够以 Windows 的保护机制保护起来&#xff0c;不被轻易反编译的话&#xff0c;那么这篇文章应该能帮到你。介绍MSIX 是微软于去年的 Windows 开发者日峰会 上推出的全新应用打包解决方案。其目的是取代旧式的软件打包方式&#xff0c;可用于 Win32、W…

使用 C# 和 Blazor 进行全栈开发

Blazor 是将 C# 引入浏览器的 Microsoft 试验框架&#xff0c;正好可以填补欠缺的 C# 一环。如今&#xff0c;C# 程序员可以编写桌面、服务器端 Web、云、电话、平板电脑、手表、电视和 IoT 应用程序。Blazor 填补了欠缺的一环&#xff0c;C# 开发人员现在可以直接在用户浏览器…

AWS vs K8s 是新的 Windows vs Linux

作者&#xff1a;Ian Miell是开源程序员、演讲师、作家和博客写手以前……如果你与我一样&#xff0c;年过四十&#xff0c;又在IT行业工作&#xff0c;恐怕还记得每个人使用Windows&#xff0c;一小群但越来越多的人在业余时间埋头编译Linux的年代。Windows用户见此情形会困惑…

Asp.Net Core中的静态文件-12

目录本文出自《从零开始学 ASP.NET CORE MVC》目录 推荐文章&#xff1a;配置 ASP.NET Core 请求(Request)处理管道Asp.Net Core 中的静态文件在这个视频中我们将讨论如何使 ASP.NET Core 应用程序&#xff0c;支持静态文件&#xff0c;如 HTML&#xff0c;图像&#xff0c;CSS…

在.net core 中PetaPoco结合EntityFrameworkCore使用codefirst方法进行开发

在.net core开发过程中&#xff0c;使用最多的就是注入方法。但是在.net core使用PetaPoco时&#xff0c;PetaPoco还不支持进行注入方式进行处理一些问题。今天对PetaPoco进行了一些扩展&#xff0c;可以很方便的将PetaPoco进行注入操作&#xff0c;使用和EF很相似&#xff0c;…

F-Pairwise Modulo

d数组是来算&#xff08;x整除y&#xff09;*y中y比x小的数 s数组是算&#xff08;x整除y&#xff09;*y中y比x大的数 &#xff08;x整除y&#xff09;*y 看x对于前面大于他的数是枚举&#xff0c;对于前面小于他的数是d树状数组储存。 d中 x整除y表示x中有多少个y 所以 …

【微服务学习】Polly:熔断降级组件

何为熔断降级“熔断器如同电力过载保护器。它可以实现快速失败&#xff0c;如果它在一段时间内侦测到许多类似的错误&#xff0c;会强迫其以后的多个调用快速失败&#xff0c;不再访问远程服务器&#xff0c;从而防止应用程序不断地尝试执行可能会失败的操作&#xff0c;使得应…

A - Junk-Mail Filter HDU - 2473

只是这样合并&#xff0c;分割点的时候就不能分了。 这样合并再加上虚拟节点&#xff0c;那么每个你要求的节点就的下面就不连其他节点了&#xff0c;这样就可以进行删除操作了 #include<iostream> #include<algorithm> #include<cstdio> #include<cstr…

为什么不要使用 async void

问题在使用 Abp 框架的后台作业时&#xff0c;当后台作业抛出异常&#xff0c;会导致整个程序崩溃。在 Abp 框架的底层执行后台作业的时候&#xff0c;有 try/catch 语句块用来捕获后台任务执行时的异常&#xff0c;但是在这里没有生效。原始代码如下&#xff1a;public class …

张队长主讲这堂 .NET Core技术培训公开课,太原你约不约

这堂.NET Core技术培训课&#xff0c;你不能错过各位开发者朋友们想必也能体会到&#xff0c;现在市面上关于.NET Core的培训课程少之又少&#xff0c;其中有质量有内容的课程更是凤毛麟角&#xff0c;良师难遇&#xff0c;一课难求。但是现在&#xff0c;机会来了。中微云孵邀…

微软推出新语言Bosque,超越结构化程序设计

微软近期推出了一款全新的编程语言 Bosque&#xff0c;该语言参考了 TypeScript 的语法与类型&#xff0c;还有 ML 和 Node/JavaScript 的语义。作者微软计算机科学家 Mark Marron 致力于消除编程过程中出现的各种复杂情况&#xff0c;创造出了他认为超越主流结构化程序设计的 …

vue 实验报告8 基于Nuxt.js开发一个Vue程序,实现登录和注册切换

一、步骤&#xff1a; 保证node.js版本在14以上 1. 全局安装create-nuxt-app: npm install -g create-nuxt-app2.9.x 2. 创建项目: create-nuxt-app my-nuxt-demo 选项这么选&#xff1a; 然后输入&#xff1a; cd my-nuxt-demo 3. 创建登录和注册页面: 在/pages目录下创建logi…

解决vs2019中暂时无法为.net core WinForms使用 Designer 的临时方法

以下方法来自于微软github开源项目WinForms:dotnet/winforms - Using the Classic WinForms Designer in WinForms Core, 请放心使用 .目前.net core下的 Windows Forms的可视化设计器(Designer)尚不可用&#xff0c;后续的Visual Studio 2019 Update才会支持该部分的功能。不过…

P2480 [SDOI2010]古代猪文(数论好题)

P2480 [SDOI2010]古代猪文 题意&#xff1a; 给你n和g&#xff0c;求g∑d∣nCndmodpg^{\sum_{d|n}C_{n}^{d}}\bmod pg∑d∣n​Cnd​modp p999911659 题解&#xff1a; 这个一个综合性很强的数论题 涉及到欧拉定理&#xff0c;Lucas定理&#xff0c;中国剩余定理&#xff0c…

ASP.NET Core开发者成长路线图

来源: MoienTajik/AspNetCore-Developer-Roadmap.2019年ASP.NET Core开发者指南:你可以在下面找到一张图&#xff0c;该图展示了你可以选取的路径及你想学习的库&#xff0c;从而成为一名 ASP.NET Core 开发者。“作为 ASP.NET Core 开发者&#xff0c;我接下来应该学习什么&am…

.NET Framework VS .NET Core

本文对应的原文来至 c-sharpcorner 的一篇文章&#xff0c;文末有链接。如有错误&#xff0c;还请指正。前言你会为你的下一个应用程序选择哪一种开发平台 - .NET Framework 或者 .NET Core&#xff1f;在这篇文章中&#xff0c;让我们比较一下这两个开发平台的特点&#xff0c…

解决 VS2019 中.net core WPF 暂时无法使用 Designer 的临时方法

以下方法来自于微软github开源项目WPF:dotnet/samples - WPF Hello World sample with linked files&#xff0c;请放心使用。此篇文章是上篇文章解决vs2019中暂时无法为.net core WinForms使用 Designer 的临时方法的姊妹篇&#xff0c;但对WPF而言实现起来比WinForms简单很多…

.NET Core 迁移躺坑记

最近将自己负责的一个核心接口系统从.Net Framework迁移到了.Net Core。整体过程&#xff0c;从业务层面说一般般吧(整体还好但还是搞的业务有感&#xff0c;没出严重故障&#xff09;但是技术层面上感觉其实并没有达到要求&#xff0c;不过预期也是应该不会那么顺利&#xff0…

[Abp vNext 源码分析] - 2. 模块系统的变化

一、简要说明本篇文章主要分析 Abp vNext 当中的模块系统&#xff0c;从类型构造层面上来看&#xff0c;Abp vNext 当中不再只是单纯的通过 AbpModuleManager 来管理其他的模块&#xff0c;它现在则是 IModuleManager 和 IModuleLoader 来协同工作&#xff0c;其他的代码逻辑并…

P3301 [SDOI2013]方程

P3301 [SDOI2013]方程 题意&#xff1a; 题解&#xff1a; 插板法介绍 首先要先讲组合数学的一个方法&#xff1a;插板法 问题引出&#xff1a;把10个球放进三个盒子&#xff0c;每个箱子至少一个有多少种分法&#xff1f; 10个球就有9个空隙&#xff0c;我们可以考虑在这个…