ABP VNext 系列:框架启动流程以及依赖注入原理和源码分析
简单介绍 ABP VNext
Github 地址:https://github.com/abpframework/abp
官网文档地址:https://abp.io/docs/latest
官网:https://abp.io/
- ABP VNext 框架是一个基于 ASP.NET Core 的完整基础架构,也就是我们现在称的 ABP 框架,它遵循软件开发最佳实践和最新技术来创建现代 Web 应用程序和 API。
- ABP vNext 是 ABP 框架作者所发起的新项目,ABP vNext 框架核心库比 ABP 框架更加精简,因为将原有许多的组件从其核心库抽离成独立的组件。这样开发人员可以更加灵活的选择自己需要的功能进行集成,使项目远离臃肿的库。
- ABP 提供了基于领域驱动设计原则和模式的完整、模块化和分层的软件架构。它还提供了实现此架构所需的基础架构和指导。
- ABP 框架提供了许多功能来更轻松地实现实际场景,例如事件总线、后台作业系统、审计日志、BLOB 存储、数据播种、数据过滤等。
框架启动流程
模块化文档:https://abp.io/docs/latest/framework/architecture/modularity/basics
下载源码:https://github.com/abpframework/abp/tree/dev/framework
参考构建一个新 ASP.NET Core MVC 的项目:https://abp.io/docs/latest/get-started/empty-aspnet-core-application
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseAutofac(); //推荐使用Autofac作为依赖注入框架
//注入ABP相关服务
await builder.Services.AddApplicationAsync<MCodeAbpWebModule>();
var app = builder.Build();
//初始化程序
await app.InitializeApplicationAsync();
await app.RunAsync();
}
}
/// <summary>
/// 需要什么模块引入什么模块,才会注入
/// </summary>
[DependsOn(
typeof(AbpAspNetCoreMvcModule),
typeof(AbpSwashbuckleModule),
typeof(MCodeAbpApplicationModule),
typeof(AbpAutofacModule)
)]
public class MCodeAbpWebModule : AbpModule
{
/// <summary>
/// 将你的服务添加到依赖注入系统并配置其他模块的
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
{
var service = context.Services;
//设置api格式
service.AddControllers();
//动态Api
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(MCodeAbpApplicationModule).Assembly, options => options.RemoteServiceName = "v1");
//统一前缀
options.ConventionalControllers.ConventionalControllerSettings.ForEach(x => x.RootPath = "api/app");
});
///配置 Swagger
service.AddAbpSwaggerGen(options =>
{
var serviceProvider = service.BuildServiceProvider();
var mvcOptions = serviceProvider.GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>();
var mvcSettings = mvcOptions.Value.ConventionalControllers.ConventionalControllerSettings.DistinctBy(x => x.RemoteServiceName);
options.SwaggerDoc("v1", new OpenApiInfo { Title = "mcode.abp.api", Version = "v1", Description = "mcode.abp.api" });
// 根据分组名称过滤 API 文档(必须) *****
options.DocInclusionPredicate((docName, apiDesc) =>
{
if (apiDesc.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
{
var settingOrNull = mvcSettings.Where(x => x.Assembly == controllerActionDescriptor.ControllerTypeInfo.Assembly).FirstOrDefault();
if (settingOrNull is not null)
{
return docName == settingOrNull.RemoteServiceName;
}
}
return false;
});
//配置模型标识,默认type.Name,名称一样,不同明明空间会报错,所以改成FullName,加上命名空间区分
options.CustomSchemaIds(type => type.FullName);
});
return Task.CompletedTask;
}
/// <summary>
/// 在应用程序启动时执行代码
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
app.UseStaticFiles();
app.UseRouting();
app.UseSwagger();
app.UseAbpSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "mcode.abp.api");
});
app.UseConfiguredEndpoints();
return Task.CompletedTask;
}
}
public class MCodeAbpApplicationModule : AbpModule
{
}
/// <summary>
///扩展示例
/// </summary>
[Route("[controller]/[action]")]
public class TestService : ApplicationService
{
/// <summary>
/// 动态Api
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
public string GetHelloWorld(string? name)
{
return name ?? "HelloWord";
}
}
源码分析
替换 IOC 容器
通过 UseServiceProviderFactory()
方法 ,构建 Abp 自定义的 Autofac 容器工厂,实际上就是做了一层包装
public static class AbpAutofacHostBuilderExtensions
{
public static IHostBuilder UseAutofac(this IHostBuilder hostBuilder)
{
//初始化AutoFac容器构建对象
var containerBuilder = new ContainerBuilder();
return hostBuilder.ConfigureServices((_, services) =>
{
services.AddObjectAccessor(containerBuilder);
})
//注册Abp自定义的Autofac容器工厂
.UseServiceProviderFactory(new AbpAutofacServiceProviderFactory(containerBuilder));
}
}
添加 ABP 应用程序
通过 AbpApplicationFactory
类工厂创建启动模块程序
public async static Task<IAbpApplicationWithExternalServiceProvider> AddApplicationAsync<TStartupModule>(
[NotNull] this IServiceCollection services,
Action<AbpApplicationCreationOptions>? optionsAction = null)
where TStartupModule : IAbpModule
{
return await AbpApplicationFactory.CreateAsync<TStartupModule>(services, optionsAction);
}
/// <summary>
/// 通过 AbpApplicationFactory 创建 ABP 应用程序
/// </summary>
/// <typeparam name="TStartupModule"></typeparam>
/// <param name="services"></param>
/// <param name="optionsAction"></param>
/// <returns></returns>
public async static Task<IAbpApplicationWithExternalServiceProvider> CreateAsync<TStartupModule>(
[NotNull] IServiceCollection services,
Action<AbpApplicationCreationOptions>? optionsAction = null)
where TStartupModule : IAbpModule
{
var app = Create(typeof(TStartupModule), services, options =>
{
options.SkipConfigureServices = true;
optionsAction?.Invoke(options);
});
//调用配置服务
await app.ConfigureServicesAsync();
return app;
}
创建 ABP 外部服务提供者
AbpApplicationWithExternalServiceProvider
中构造方法只做了了一件事,就是添加自己到服务中去。
核心是继承了 AbpApplicationBase
基类,实例化后会调用基类的构造方法
/// <summary>
/// 创建 ABP 外部服务提供者(实例化应用程序基类)
/// </summary>
/// <param name="startupModuleType"></param>
/// <param name="services"></param>
/// <param name="optionsAction"></param>
/// <returns></returns>
public static IAbpApplicationWithExternalServiceProvider Create(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
Action<AbpApplicationCreationOptions>? optionsAction = null)
{
//会实例化ABP应用程序基类
return new AbpApplicationWithExternalServiceProvider(startupModuleType, services, optionsAction);
}
初始化 ABP 程序基类
模块的初始化动作是在 AbpApplicationBase
基类开始的,在该基类当中除了注入模块相关的基础设施以外。
还定义了模块的初始化方法,即 LoadModules()
方法,在该方法内部是调用的 IModuleLoader
去执行具体的加载操作
/// <summary>
/// 初始化 Abp 程序
/// </summary>
/// <param name="startupModuleType"></param>
/// <param name="services"></param>
/// <param name="optionsAction"></param>
internal AbpApplicationBase(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
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);
//将Services添加到配置中去
optionsAction?.Invoke(options);
//获取应用程序名称
ApplicationName = GetApplicationName(options);
//添加当前对象为各种服务实例
services.AddSingleton<IAbpApplication>(this);
services.AddSingleton<IApplicationInfoAccessor>(this);
services.AddSingleton<IModuleContainer>(this);
//添加环境变量
services.AddSingleton<IAbpHostEnvironment>(new AbpHostEnvironment()
{
EnvironmentName = options.Environment
});
//添加日志、选项等
services.AddCoreServices();
//添加核心Abp服务,以及模块的四个应用程序生命周期
services.AddCoreAbpServices(this, options);
//读取所有的模块,并按照预加载、初始化、初始化完成的顺序执行其生命周期方法
Modules = LoadModules(services, options);
//默认为true,不执行
if (!options.SkipConfigureServices)
{
ConfigureServices();
}
}
添加核心 ABP 服务
AddCoreServices()
方法中是添加包括常规的日志、选项、本地化。
AddCoreAbpServices()
方法则是 添加 Abp 的核心服务,包括各种读取器,配置
/// <summary>
/// 添加核心服务
/// </summary>
/// <param name="services"></param>
internal static void AddCoreServices(this IServiceCollection services)
{
//添加选项
services.AddOptions();
//添加日志
services.AddLogging();
//添加本地化
services.AddLocalization();
}
/// <summary>
/// 添加核心ABP服务
/// </summary>
/// <param name="services"></param>
/// <param name="abpApplication"></param>
/// <param name="applicationCreationOptions"></param>
internal static void AddCoreAbpServices(this IServiceCollection services,
IAbpApplication abpApplication,
AbpApplicationCreationOptions applicationCreationOptions)
{
var moduleLoader = new ModuleLoader();
var assemblyFinder = new AssemblyFinder(abpApplication);
var typeFinder = new TypeFinder(assemblyFinder);
if (!services.IsAdded<IConfiguration>())
{
services.ReplaceConfiguration(
ConfigurationHelper.BuildConfiguration(
applicationCreationOptions.Configuration
)
);
}
//添加各种读取器和查找器
services.TryAddSingleton<IModuleLoader>(moduleLoader);
services.TryAddSingleton<IAssemblyFinder>(assemblyFinder);
services.TryAddSingleton<ITypeFinder>(typeFinder);
services.TryAddSingleton<IInitLoggerFactory>(new DefaultInitLoggerFactory());
//添加 AbpApplication所在程序集的类型
services.AddAssemblyOf<IAbpApplication>();
services.AddTransient(typeof(ISimpleStateCheckerManager<>), typeof(SimpleStateCheckerManager<>));
//配置生命周期选项
services.Configure<AbpModuleLifecycleOptions>(options =>
{
options.Contributors.Add<OnPreApplicationInitializationModuleLifecycleContributor>();
options.Contributors.Add<OnApplicationInitializationModuleLifecycleContributor>();
options.Contributors.Add<OnPostApplicationInitializationModuleLifecycleContributor>();
options.Contributors.Add<OnApplicationShutdownModuleLifecycleContributor>();
});
}
读取模块
进入 IModuleLoader
的默认实现 ModuleLoader
,在它的 LoadModules()
方法中,基本逻辑如下:
扫描当前应用程序的所有模块类,并构建模块描述对象。
基于模块描述对象,使用拓扑排序算法来按照模块的依赖性进行排序。
排序完成之后,遍历排序完成的模块描述对象,依次执行它们的三个生命周期方法。
protected virtual IReadOnlyList<IAbpModuleDescriptor> LoadModules(IServiceCollection services, AbpApplicationCreationOptions options)
{
//通过ModelLoader实例读取模块,LoadModules的时候会将实例添加到容器中
return services
.GetSingletonInstance<IModuleLoader>()
.LoadModules(
services,
StartupModuleType,
options.PlugInSources
);
}
/// <summary>
/// 读取模块
/// </summary>
/// <param name="services"></param>
/// <param name="startupModuleType"></param>
/// <param name="plugInSources"></param>
/// <returns></returns>
public IAbpModuleDescriptor[] LoadModules(
IServiceCollection services,
Type startupModuleType,
PlugInSourceList plugInSources)
{
Check.NotNull(services, nameof(services));
Check.NotNull(startupModuleType, nameof(startupModuleType));
Check.NotNull(plugInSources, nameof(plugInSources));
//获取模块说明
var modules = GetDescriptors(services, startupModuleType, plugInSources);
//排序
modules = SortByDependency(modules, startupModuleType);
return modules.ToArray();
}
/// <summary>
/// 获取模块说明
/// </summary>
/// <param name="services"></param>
/// <param name="startupModuleType"></param>
/// <param name="plugInSources"></param>
/// <returns></returns>
private List<IAbpModuleDescriptor> GetDescriptors(
IServiceCollection services,
Type startupModuleType,
PlugInSourceList plugInSources)
{
var modules = new List<AbpModuleDescriptor>();
//查找Module
FillModules(modules, services, startupModuleType, plugInSources);
//添加到当前模块描述对象的 Dependencies 属性
SetDependencies(modules);
return modules.Cast<IAbpModuleDescriptor>().ToList();
}
/// <summary>
/// 查找所有的模块
/// </summary>
/// <param name="modules"></param>
/// <param name="services"></param>
/// <param name="startupModuleType"></param>
/// <param name="plugInSources"></param>
protected virtual void FillModules(
List<AbpModuleDescriptor> modules,
IServiceCollection services,
Type startupModuleType,
PlugInSourceList plugInSources)
{
var logger = services.GetInitLogger<AbpApplicationBase>();
//查找到所有的模块
//All modules starting from the startup module
foreach (var moduleType in AbpModuleHelper.FindAllModuleTypes(startupModuleType, logger))
{
//创建模块说明并添加到容器中去
modules.Add(CreateModuleDescriptor(services, moduleType));
}
//Plugin modules
foreach (var moduleType in plugInSources.GetAllModules(logger))
{
if (modules.Any(m => m.Type == moduleType))
{
continue;
}
modules.Add(CreateModuleDescriptor(services, moduleType, isLoadedAsPlugIn: true));
}
}
配置服务(注入上下文、执行其生命周期方法)
创建完 Abp 应用程序后会调用 ConfigureServicesAsync()
方法 ,
会执行每个模块中的:ConfigureServices()
、PreConfigureServices()
、PostConfigureServices()
方法等
/// <summary>
/// 配置服务
/// </summary>
/// <returns></returns>
/// <exception cref="AbpInitializationException"></exception>
public virtual async Task ConfigureServicesAsync()
{
CheckMultipleConfigureServices();
//将服务配置上下文对象添加到容器中
var context = new ServiceConfigurationContext(Services);
Services.AddSingleton(context);
//遍历所有的容器中的模块,并指定上下文对象
foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
abpModule.ServiceConfigurationContext = context;
}
}
//遍历执行模块中PreConfigureServicesAsync方法(ConfigureServices之前执行)
foreach (var module in Modules.Where(m => m.Instance is IPreConfigureServices))
{
try
{
await ((IPreConfigureServices)module.Instance).PreConfigureServicesAsync(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IPreConfigureServices.PreConfigureServicesAsync)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
}
}
var assemblies = new HashSet<Assembly>();
////遍历模块,将所有的模块中需要注入的进行注入
foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
if (!abpModule.SkipAutoServiceRegistration)
{
foreach (var assembly in module.AllAssemblies)
{
if (!assemblies.Contains(assembly))
{
Services.AddAssembly(assembly);
assemblies.Add(assembly);
}
}
}
}
try
{
//执行模块实例中的方法
await module.Instance.ConfigureServicesAsync(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IAbpModule.ConfigureServicesAsync)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
}
}
//遍历执行模块中PostConfigureServicesAsync方法(ConfigureServices之后执行)
foreach (var module in Modules.Where(m => m.Instance is IPostConfigureServices))
{
try
{
await ((IPostConfigureServices)module.Instance).PostConfigureServicesAsync(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IPostConfigureServices.PostConfigureServicesAsync)} 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!;
}
}
_configuredServices = true;
TryToSetEnvironment(Services);
}
组件自动注册源码分析
ABP 提供了三种接口:ISingletonDependency
和 ITransientDependency
、IScopedDependency
接口的方式进行注入
方便我们的类型/组件自动注册,这三种接口分别对应了对象的 单例、瞬时、范围 生命周期。
只要任何类型/接口实现了以上任意接口,ABP vNext 就会在系统启动时候,将这些对象注册到 IoC 容器当中
也可以通过 DependencyAttribute
特性 去标记服务的类型,指定服务的生命周期
在模块系统调用模块的 ConfigureServicesAsync()
的时候,就会有一个 services.AddAssembly()
方法,
他会将模块的所属的程序集传入
//ConfigureServices
foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
//是否跳过服务的自动注册,默认为 false
if (!abpModule.SkipAutoServiceRegistration)
{
foreach (var assembly in module.AllAssemblies)
{
if (!assemblies.Contains(assembly))
{
//注入当前程序集
Services.AddAssembly(assembly);
assemblies.Add(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);
}
}
通过获取规则注册器进行注册,Abp 框架中自带默认的注册器 DefaultConventionalRegistrar
,也可以自定义注册器
通过实现 ConventionalRegistrarBase
抽象类去自定义
public static IServiceCollection AddAssembly(this IServiceCollection services, Assembly assembly)
{
///获得所有注册器,然后调用注册器的 AddAssembly 方法注册类型。
foreach (var registrar in services.GetConventionalRegistrars())
{
registrar.AddAssembly(services, assembly);
}
return services;
}
//抽象基类
public abstract class ConventionalRegistrarBase : IConventionalRegistrar
{
/// <summary>
///
/// </summary>
/// <param name="services"></param>
/// <param name="assembly"></param>
public virtual void AddAssembly(IServiceCollection services, Assembly assembly)
{
//获得程序集内的所有类型,过滤掉抽象类和泛型类型。
var types = AssemblyHelper
.GetAllTypes(assembly)
.Where(
type => type != null &&
type.IsClass &&
!type.IsAbstract &&
!type.IsGenericType
).ToArray();
AddTypes(services, types);
}
//添加类型
public virtual void AddTypes(IServiceCollection services, params Type[] types)
{
foreach (var type in types)
{
AddType(services, type);
}
}
public abstract void AddType(IServiceCollection services, Type type);
}
- 通过的默认注册器进行注册
public class DefaultConventionalRegistrar : ConventionalRegistrarBase
{
/// <summary>
/// 添加类型
/// </summary>
/// <param name="services"></param>
/// <param name="type"></param>
public override void AddType(IServiceCollection services, Type type)
{
//如果标记了:DisableConventionalRegistrationAttribute特性的,不进行注入
if (IsConventionalRegistrationDisabled(type))
{
return;
}
//获取Dependency依赖特性
var dependencyAttribute = GetDependencyAttributeOrNull(type);
//获取生命周期
var lifeTime = GetLifeTimeOrNull(type, dependencyAttribute);
if (lifeTime == null)
{
return;
}
//转成服务标识
var exposedServiceAndKeyedServiceTypes = GetExposedKeyedServiceTypes(type).Concat(GetExposedServiceTypes(type).Select(t => new ServiceIdentifier(t))).ToList();
//生成服务
TriggerServiceExposing(services, type, exposedServiceAndKeyedServiceTypes);
foreach (var exposedServiceType in exposedServiceAndKeyedServiceTypes)
{
var allExposingServiceTypes = exposedServiceType.ServiceKey == null
? exposedServiceAndKeyedServiceTypes.Where(x => x.ServiceKey == null).ToList()
: exposedServiceAndKeyedServiceTypes.Where(x => x.ServiceKey?.ToString() == exposedServiceType.ServiceKey?.ToString()).ToList();
//创建服务描述
var serviceDescriptor = CreateServiceDescriptor(
type,
exposedServiceType.ServiceKey,
exposedServiceType.ServiceType,
allExposingServiceTypes,
lifeTime.Value
);
if (dependencyAttribute?.ReplaceServices == true)
{
services.Replace(serviceDescriptor);
}
else if (dependencyAttribute?.TryRegister == true)
{
services.TryAdd(serviceDescriptor);
}
else
{
services.Add(serviceDescriptor);
}
}
}
}
- 从
GetLifeTimeOrNull
方法中 获取生命周期
/// <summary>
/// 获取生命周期
/// </summary>
/// <param name="type"></param>
/// <param name="dependencyAttribute"></param>
/// <returns></returns>
protected virtual ServiceLifetime? GetLifeTimeOrNull(Type type, DependencyAttribute? dependencyAttribute)
{
// 特性中设置了生命周期或者继承了接口
return dependencyAttribute?.Lifetime ?? GetServiceLifetimeFromClassHierarchy(type) ?? GetDefaultLifeTimeOrNull(type);
}
/// <summary>
/// 从接口中获取生命周期
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
protected virtual ServiceLifetime? GetServiceLifetimeFromClassHierarchy(Type type)
{
if (typeof(ITransientDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Transient;
}
if (typeof(ISingletonDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Singleton;
}
if (typeof(IScopedDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Scoped;
}
return null;
}
初始化 ABP 应用程序
- 通过
await app.InitializeApplicationAsync();
方法会初始化应用程序,然后执行每一个模块中的生命周期的方法
/// <summary>
/// 异步初始化 ABP 应用程序
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public async static Task InitializeApplicationAsync([NotNull] this IApplicationBuilder app)
{
Check.NotNull(app, nameof(app));
app.ApplicationServices.GetRequiredService<ObjectAccessor<IApplicationBuilder>>().Value = app;
var application = app.ApplicationServices.GetRequiredService<IAbpApplicationWithExternalServiceProvider>();
var applicationLifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
//注册程序生命周期停止事件
applicationLifetime.ApplicationStopping.Register(() =>
{
//执行 Abp程序中的 ShutdownAsync 方法, 会调用每个模块中的 ShutdownAsync 方法
AsyncHelper.RunSync(() => application.ShutdownAsync());
});
//释放 Abp 应用
applicationLifetime.ApplicationStopped.Register(() =>
{
application.Dispose();
});
// 执行 初始化 Abp 方法 ,初始化 每个模块,执行每一个模块中的 InitializeAsync 方法
await application.InitializeAsync(app.ApplicationServices);
}
- 初始化每一个模块生命周期方法
/// <summary>
/// 设置服务提供者
/// </summary>
/// <param name="serviceProvider"></param>
protected virtual void SetServiceProvider(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
ServiceProvider.GetRequiredService<ObjectAccessor<IServiceProvider>>().Value = ServiceProvider;
}
/// <summary>
/// 初始化模块
/// </summary>
/// <returns></returns>
protected virtual async Task InitializeModulesAsync()
{
using (var scope = ServiceProvider.CreateScope())
{
WriteInitLogs(scope.ServiceProvider);
await scope.ServiceProvider
.GetRequiredService<IModuleManager>() //初始化模块
.InitializeModulesAsync(new ApplicationInitializationContext(scope.ServiceProvider));
}
}
/// <summary>
/// 初始化模块
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
/// <exception cref="AbpInitializationException"></exception>
public virtual async Task InitializeModulesAsync(ApplicationInitializationContext context)
{
// 原先在 AddCoreAbpServices() 方法中 配置的 生命周期,
foreach (var contributor in _lifecycleContributors)
{
foreach (var module in _moduleContainer.Modules)
{
try
{
//执行每个生命周期(加载之前、加载中、加载之后)中的 初始化方法
await contributor.InitializeAsync(context, module.Instance);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during the initialize {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}: {ex.Message}. See the inner exception for details.", ex);
}
}
}
_logger.LogInformation("Initialized all ABP modules.");
}
- 四个生命周期
OnApplicationInitializationModuleLifecycleContributor
、
OnPreApplicationInitializationModuleLifecycleContributor
、
OnPostApplicationInitializationModuleLifecycleContributor
OnApplicationShutdownModuleLifecycleContributor
中的方法,实际就是调用到具体模块中的生命周期各个方法
public class OnApplicationInitializationModuleLifecycleContributor : ModuleLifecycleContributorBase
{
public async override Task InitializeAsync(ApplicationInitializationContext context, IAbpModule module)
{
if (module is IOnApplicationInitialization onApplicationInitialization)
{
await onApplicationInitialization.OnApplicationInitializationAsync(context);
}
}
public override void Initialize(ApplicationInitializationContext context, IAbpModule module)
{
(module as IOnApplicationInitialization)?.OnApplicationInitialization(context);
}
}
public class OnApplicationShutdownModuleLifecycleContributor : ModuleLifecycleContributorBase
{
public async override Task ShutdownAsync(ApplicationShutdownContext context, IAbpModule module)
{
if (module is IOnApplicationShutdown onApplicationShutdown)
{
await onApplicationShutdown.OnApplicationShutdownAsync(context);
}
}
public override void Shutdown(ApplicationShutdownContext context, IAbpModule module)
{
(module as IOnApplicationShutdown)?.OnApplicationShutdown(context);
}
}
public class OnPreApplicationInitializationModuleLifecycleContributor : ModuleLifecycleContributorBase
{
public async override Task InitializeAsync(ApplicationInitializationContext context, IAbpModule module)
{
if (module is IOnPreApplicationInitialization onPreApplicationInitialization)
{
await onPreApplicationInitialization.OnPreApplicationInitializationAsync(context);
}
}
public override void Initialize(ApplicationInitializationContext context, IAbpModule module)
{
(module as IOnPreApplicationInitialization)?.OnPreApplicationInitialization(context);
}
}
public class OnPostApplicationInitializationModuleLifecycleContributor : ModuleLifecycleContributorBase
{
public async override Task InitializeAsync(ApplicationInitializationContext context, IAbpModule module)
{
if (module is IOnPostApplicationInitialization onPostApplicationInitialization)
{
await onPostApplicationInitialization.OnPostApplicationInitializationAsync(context);
}
}
public override void Initialize(ApplicationInitializationContext context, IAbpModule module)
{
(module as IOnPostApplicationInitialization)?.OnPostApplicationInitialization(context);
}
}
ABP VNext 系列:框架启动流程以及依赖注入原理和源码分析的更多相关文章
- PHP依赖注入原理与用法分析
https://www.jb51.net/article/146025.htm 本文实例讲述了PHP依赖注入原理与用法.分享给大家供大家参考,具体如下: 引言 依然是来自到喜啦的一道面试题,你知道什么 ...
- 小白都能看懂的 Spring 源码揭秘之依赖注入(DI)源码分析
目录 前言 依赖注入的入口方法 依赖注入流程分析 AbstractBeanFactory#getBean AbstractBeanFactory#doGetBean AbstractAutowireC ...
- ☕【Java深层系列】「并发编程系列」让我们一起探索一下CyclicBarrier的技术原理和源码分析
CyclicBarrier和CountDownLatch CyclicBarrier和CountDownLatch 都位于java.util.concurrent这个包下,其工作原理的核心要点: Cy ...
- ABP vNext系列文章03---依赖注入
一.依赖注入的类型注册 ABP的依赖注入系统是基于Microsoft的依赖注入扩展库(Microsoft.Extensions.DependencyInjection nuget包)开发的.因此,它的 ...
- 【17MKH】我在框架中对.Net依赖注入的扩展
说明 依赖注入(DI)是控制反转(IoC)的一种技术实现,它应该算是.Net中最核心,也是最基本的一个功能.但是官方只是实现了基本的功能和扩展方法,而我呢,在自己的框架 https://github. ...
- Java自动化测试框架-09 - TestNG之依赖注入篇 (详细教程)
1.-依赖注入 TestNG支持两种不同类型的依赖项注入:本机(由TestNG本身执行)和外部(由诸如Guice的依赖项注入框架执行). 1.1-本机依赖项注入 TestNG允许您在方法中声明其他参数 ...
- [Spark内核] 第32课:Spark Worker原理和源码剖析解密:Worker工作流程图、Worker启动Driver源码解密、Worker启动Executor源码解密等
本課主題 Spark Worker 原理 Worker 启动 Driver 源码鉴赏 Worker 启动 Executor 源码鉴赏 Worker 与 Master 的交互关系 [引言部份:你希望读者 ...
- Spring依赖注入原理分析
在分析原理之前我们先回顾下依赖注入的概念: 我们常提起的依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念.具体含义是:当某个角色( ...
- Spring Boot启动命令参数详解及源码分析
使用过Spring Boot,我们都知道通过java -jar可以快速启动Spring Boot项目.同时,也可以通过在执行jar -jar时传递参数来进行配置.本文带大家系统的了解一下Spring ...
- 【串线篇】spring泛型依赖注入原理
spring泛型依赖注入原理 不管三七二十一 servlet :加注解@servlet service:加注解@service dao:加注解@Repository 这相当于在容器中注册这些个类
随机推荐
- 【ECharts】01 快速上手
简单介绍: ECharts 是一个使用 JavaScript 实现的开源可视化库,涵盖各行业图表,满足各种需求. ECharts 遵循 Apache-2.0 开源协议,免费商用. ECharts 兼容 ...
- jdk命令行工具系列——检视阅读
jdk命令行工具系列--检视阅读 参考 java虚拟机系列 RednaxelaFX知乎问答 RednaxelaFX博客 jps--虚拟机进程状态工具 jps :(JVM Process Status ...
- NVIDIA机器人仿真项目 —— Isaac Gym - Preview Release
地址: https://developer.nvidia.com/isaac-gym 过期代码库地址:(已不再维护的代码库,现已由isaac gym项目合并到isaac sim项目)(2022年开始停 ...
- 并行化强化学习 —— 初探 —— 并行reinforce算法的尝试 (上篇:强化学习在多仿真环境下单步交互并行化设计的可行性)
强化学习由于难收敛所以训练周期较长,同时由于强化学习在训练过程中起训练数据一般都为实时生成的,因此在训练的同时算法还需要生成待训练的数据,强化学习算法的基本架构可以视作下图:(取自:深度学习中使用Te ...
- Python多进程共享numpy 数组
引用:https://zhuanlan.zhihu.com/p/32513483 共享 numpy 数组 需要用到 numpy 时往往是数据量较大的场景,如果直接复制会造成大量内存浪费.共享 nump ...
- 如何在vscode中支持python的annotation(注解,type checking)——通过设置pylance参数实现python注解的type checking
pylance是vscode的python官方插件的捆绑体,如何在vscode中安装python插件这里不介绍了.pylance的默认设置是不支持python的annotation的,需要我们手动设置 ...
- js 实现俄罗斯方块(三)
我又来啦!上一篇有点水,本篇我们来干货! 嘿嘿,首先我们先搭建游戏世界------网格 所有的操作包括左移右移下移旋转都是在这个网格中 既然是使用js来写当然跑不了html啦,实现网格最简单的 方法就 ...
- CentOS ssh版本升级
1.升级openssl yum install perl wget https://goodrain-delivery.oss-cn-hangzhou.aliyuncs.com/fuzhoushuch ...
- k8s-使用Network Policies实现网络隔离
一.需求 Kubernetes 的命名空间主要用于组织和隔离资源,但默认情况下,不同命名空间中的 Pod 之间是可以相互通信的.为了实现更严格的网络隔离,同一套k8s需要根据不同的命名空间进行网络环境 ...
- 【测试平台开发】——07Vue前端框架实战——restful请求
本节主要是前后端接口的调用,以及前端如何进行封装接口 一.创建相关文件 在文件夹下创建http.js.api.js.user.js 1)http.js封装接口: 在src下创建api文件夹 添加htt ...