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 ...
随机推荐
- 微信小程序授权登录将open_id传至后台并入库
要求能把用户昵称.头像以及open_id写入数据库,服务端保持用户登录状态 wxml: <block wx:else> <button type="primary" ...
- linux定时任务 - crontab定时任务
crontab 定时任务命令 linux 系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的.另 外, 由于使用者 ...
- egg-jwt的使用
安装 npm install egg-jwt --save 配置 // config/config.default.js config.jwt = { secret: 'zidingyi', // 自 ...
- springboot Redistemplate的execute和 executePipelined
springboot 的 RedisTemplate 的 execute 和 executePipelined 功能的区别 1.execute 以下是 springboot 官网原文: Redis p ...
- json.dumps参数之解
宝藏参数,懂的都懂^-^ 说明:编译后print()打印内容,此内容以字符串紧凑输出,且无顺序,中文不可读.. 应用:使用pycharm做接口测试时,print()打印出的接口下行,如下图: ...
- 内网渗透----Linux信息收集整理
一.基础信息收集 1.查看系统类型 cat /etc/issue cat /etc/*-release cat /etc/lsb-release cat /etc/redhat-release 2.内 ...
- 为什么等待和通知是在 Object 类而不是 Thread 中声明的?
一个棘手的 Java 问题,如果 Java编程语言不是你设计的,你怎么能回答这个问题呢.Java编程的常识和深入了解有助于回答这种棘手的 Java 核心方面的面试问题.为什么 wait,notify ...
- oracle.i18n.text.convert.CharacterConverterOGS.getInstance(I)Loracle/i18n/text/converter/CharacterConver;
看看项目是不是同时包含ojdbc系列jar包和nls_charset12.jar包.如果同时包含,则删除nls_charset12.jar.因为低版本的nls_charset12和ojdbc包冲突.
- 什么是redis的缓存雪崩与缓存穿透?如何解决?
一.缓存雪崩 1.1 什么是缓存雪崩? 首先我们先来回答一下我们为什么要用缓存(Redis): 1.提高性能能:缓存查询是纯内存访问,而硬盘是磁盘访问,因此缓存查询速度比数据库查询速度快 2.提高并发 ...
- Linux常用命令-学习笔记
Linux命令格式: 命令 [命令参数] [命令对象] # 命令之间的参数和对象用单个空格进行分割 # "[]"代表可选,{}代表必选其中的一项,|代表或者的关系,<> ...