ABP源码分析 - 服务配置(1)
比较随意,记录下过程,以便忘了以后重拾。
三个关注点
Program.cs
internal static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac() // 第一个关注点
.UseSerilog();
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<AuthCenterWebModule>(); // 第二个关注点
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.InitializeApplication(); // 第三个关注点
}
}
services.AddApplication()过程
public static IAbpApplicationWithExternalServiceProvider AddApplication<TStartupModule>(
[NotNull] this IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
where TStartupModule : IAbpModule
{
// Factory工厂创建AbpApplication
return AbpApplicationFactory.Create<TStartupModule>(services, optionsAction);
}
public static IAbpApplicationWithExternalServiceProvider Create<TStartupModule>(
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
where TStartupModule : IAbpModule
{
return Create(typeof(TStartupModule), services, optionsAction);
}
public static IAbpApplicationWithExternalServiceProvider Create(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
{
// 这里创建具体实例
return new AbpApplicationWithExternalServiceProvider(startupModuleType, services, optionsAction);
}
查看AbpApplicationWithExternalServiceProvider构造函数
public AbpApplicationWithExternalServiceProvider(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction
) : base(
startupModuleType,
services,
optionsAction)
{
// 注入自己,初始化在基类,继续查看基类
services.AddSingleton<IAbpApplicationWithExternalServiceProvider>(this);
}
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的模块是按依赖顺序的排序
Modules = LoadModules(services, options);
// 主要看这里,服务配置
ConfigureServices();
}
protected virtual void ConfigureServices()
{
// 将ServiceCollection传入ServiceConfigurationContext
var context = new ServiceConfigurationContext(Services);
Services.AddSingleton(context);
foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
// 为每个模块实例设定context, 这样通过每个模块通过上下文都可以访问ServiceCollection
abpModule.ServiceConfigurationContext = context;
}
}
// 依次调用每个模块的PreConfigureServices, ConfigureServices, PostConfigureServices
//PreConfigureServices
foreach (var module in Modules.Where(m => m.Instance is IPreConfigureServices))
{
try
{
((IPreConfigureServices)module.Instance).PreConfigureServices(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IPreConfigureServices.PreConfigureServices)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
}
}
//ConfigureServices
foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
// 执行约定注入
if (!abpModule.SkipAutoServiceRegistration)
{
Services.AddAssembly(module.Type.Assembly);
}
}
try
{
module.Instance.ConfigureServices(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IAbpModule.ConfigureServices)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
}
}
//PostConfigureServices
foreach (var module in Modules.Where(m => m.Instance is IPostConfigureServices))
{
try
{
((IPostConfigureServices)module.Instance).PostConfigureServices(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IPostConfigureServices.PostConfigureServices)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
}
}
foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
abpModule.ServiceConfigurationContext = null;
}
}
}
小结
以上实现了每个模块服务的注入,即所有模块执行PreConfigureServices,完成后所有模块执行ConfigureServices,完成后所有模块执行PostConfigureServices。
PreConfigureServices即服务注入还没开始,这里可以做些什么?
ConfigureServices注入,
PostConfigureServices所有服务已注入,这里可以做些什么?
public class AuthCenterDomainModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
}
public override void PostConfigureServices(ServiceConfigurationContext context)
{
}
}
ABP源码分析 - 服务配置(1)的更多相关文章
- C# DateTime的11种构造函数 [Abp 源码分析]十五、自动审计记录 .Net 登陆的时候添加验证码 使用Topshelf开发Windows服务、记录日志 日常杂记——C#验证码 c#_生成图片式验证码 C# 利用SharpZipLib生成压缩包 Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库
C# DateTime的11种构造函数 别的也不多说没直接贴代码 using System; using System.Collections.Generic; using System.Glob ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- ABP源码分析二:ABP中配置的注册和初始化
一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数的执行必然是完成 ...
- ABP源码分析四十四:ZERO的配置
ABP Zero模块中需要配置的地方主要集中在三块:配置静态的role,配置外部认证源,以及配置本地化语言和资源. UserManagementConfig/IUserManagementConfig ...
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- ABP源码分析四:Configuration
核心模块的配置 Configuration是ABP中设计比较巧妙的地方.其通过AbpStartupConfiguration,Castle的依赖注入,Dictionary对象和扩展方法很巧妙的实现了配 ...
- ABP源码分析七:Setting 以及 Mail
本文主要说明Setting的实现以及Mail这个功能模块如何使用Setting. 首先区分一下ABP中的Setting和Configuration. Setting一般用于需要通过外部配置文件(或数据 ...
- ABP源码分析九:后台工作任务
文主要说明ABP中后台工作者模块(BackgroundWorker)的实现方式,和后台工作模块(BackgroundJob).ABP通过BackgroundWorkerManager来管理Backgr ...
- ABP源码分析十二:本地化
本文逐个分析ABP中涉及到locaization的接口和类,以及相互之间的关系.本地化主要涉及两个方面:一个是语言(Language)的管理,这部分相对简单.另一个是语言对应得本地化资源(Locali ...
随机推荐
- 微信小程序缓冲类的封装
1:utils 目录下新建一个Cache.js文件 2:文件下书写以下代码: // 缓存类 class Cache { // 构造方法 单位秒 constructor({ expire = 3600 ...
- PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation
摘要 点云是一种重要的几何数据结构类型.由于其不规则的格式,大多数研究人员将此类数据转化为常规的三维体素网格或图像集合.然而,这使数据变得不必要的庞大,并导致问题.在本文中,我们设计了一种新型的直接处 ...
- Java案例——冒泡排序
排序:将一组数据按照固定的规则进行排列 冒泡排序:一种排序方式,对将要排序的相邻的数据进行两两比较,将较大的放在后面,依次对所有的数据进行操作,直到所有的数据按要求完成排序 冒泡排序原理: 1.如果有 ...
- 《前端运维》一、Linux基础--10定时任务
一.进程管理 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体 ...
- Python的安装教程与环境配置
安装环境:Windows7或者Windows10 Python版本:最新即可,这里选用 python 3.7.2: 一.下载:在python的官网下载python版本,需要下载对应版本(在计算机-属性 ...
- 记录java中常用的英文单词01
专业缩写 POJO(plain ordinary java object)--简单的java对象 Spring-jdbc--为了使JDBC更加易于使用,spring在JDBC API上定义了一个抽象层 ...
- mybatis缓存-二级缓存
1.2 二级缓存 [官方声明] => 如何开启[二级缓存] 默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存. 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行 ...
- BUAA_DS_聊聊链表
幸福穿着节日的盛装欢迎你. --威廉•莎士比亚<罗密欧与朱丽叶> 1. 说在前面 大家在学数组的时候小脑瓜里有没有这样的疑惑:为什么数组必须是定长的?为什么数组开太长会编译错误?数组越界为 ...
- bzoj5130 字符串的周期(kmp,最小表示法)
bzoj5130 字符串的周期(kmp,最小表示法) bzoj 题解时间 m很大,n很小. 周期很容易求,就是kmp之后n-fail[n]. 之后对于枚举所有的字符串用最小表示法,暴力搜索. 能过就完 ...
- Vue Avoided redundant navigation to current location Error
这个报错的根源就是vue-router组件,错误内容翻译一下是: Avoided redundant navigation to current location === 避免冗余导航到当前位置 这个 ...