[ABP]浅谈模块系统与 ABP 框架初始化

2018-02-09 09:55:17来源:cnblogs.com作者:myzony人点击

分享

在 ABP 框架当中所有库以及项目都是以模块的形式存在,所有模块都是继承自AbpModule 这个抽象基类,每个模块都拥有四个生命周期。分别是:

  • PreInitialze();
  • Initialize();
  • PostInitialize():
  • ShutDown();

    AddAbp<TStartipModule>()

    在初始化 ABP 框架的时候,通过 services.AddAbp<AbpTestMulitPageWebHostModule>方法将启动模块作为泛型参数传入到 AddAbp 当中。
    之后根据传入的启动模块,初始化 AbpBootstrapper,在 AbpBootstrapper 初始化的时候执行拦截器注册等操作。
    之后配置 Asp Net Core 相关服务,替换控制器、视图组件、过滤器等默认实现,改用ABP 框架的实现,并且将 Ioc 容器替换为 CastleWindsor。

    app.UseAbp()

    之前的 AddAbp 仅仅是在 ConfigureService 注入服务,紧接着就会在 Configure方法启用 Abp 中间件。

    private static void InitializeAbp(IApplicationBuilder app){var abpBootstrapper = app.ApplicationServices.GetRequiredService<AbpBootstrapper>();abpBootstrapper.Initialize();}

    可以看到在初始化 ABP 的时候,实际上是从 Ioc 容器中解析出 AbpBootStrapper 调用它的初始化方法。

    AbpBootStrapper.Initialize()

    public virtual void Initialize(){ResolveLogger();try{    RegisterBootstrapper();    IocManager.IocContainer.Install(new AbpCoreInstaller());    IocManager.Resolve<AbpPlugInManager>().PlugInSources.AddRange(PlugInSources);    IocManager.Resolve<AbpStartupConfiguration>().Initialize();    _moduleManager = IocManager.Resolve<AbpModuleManager>();    _moduleManager.Initialize(StartupModule);    _moduleManager.StartModules();}catch (Exception ex){    _logger.Fatal(ex.ToString(), ex);    throw;}}

    首先注册了日志组件,之后再次注册了 AbpBootStarpper,可能是防止 Ioc 容器没有注册成功吧。
    然后调用了 Castle 的 Install 方法,将一些核心组件通过安装器注入到容器当中。

    public void Install(IWindsorContainer container, IConfigurationStore store){container.Register(    Component.For<IUnitOfWorkDefaultOptions, UnitOfWorkDefaultOptions>().ImplementedBy<UnitOfWorkDefaultOptions>().LifestyleSingleton(),    Component.For<INavigationConfiguration, NavigationConfiguration>().ImplementedBy<NavigationConfiguration>().LifestyleSingleton(),    Component.For<ILocalizationConfiguration, LocalizationConfiguration>().ImplementedBy<LocalizationConfiguration>().LifestyleSingleton(),    Component.For<IAuthorizationConfiguration, AuthorizationConfiguration>().ImplementedBy<AuthorizationConfiguration>().LifestyleSingleton(),    Component.For<IValidationConfiguration, ValidationConfiguration>().ImplementedBy<ValidationConfiguration>().LifestyleSingleton(),    Component.For<IFeatureConfiguration, FeatureConfiguration>().ImplementedBy<FeatureConfiguration>().LifestyleSingleton(),    Component.For<ISettingsConfiguration, SettingsConfiguration>().ImplementedBy<SettingsConfiguration>().LifestyleSingleton(),    Component.For<IModuleConfigurations, ModuleConfigurations>().ImplementedBy<ModuleConfigurations>().LifestyleSingleton(),    Component.For<IEventBusConfiguration, EventBusConfiguration>().ImplementedBy<EventBusConfiguration>().LifestyleSingleton(),    Component.For<IMultiTenancyConfig, MultiTenancyConfig>().ImplementedBy<MultiTenancyConfig>().LifestyleSingleton(),    Component.For<ICachingConfiguration, CachingConfiguration>().ImplementedBy<CachingConfiguration>().LifestyleSingleton(),    Component.For<IAuditingConfiguration, AuditingConfiguration>().ImplementedBy<AuditingConfiguration>().LifestyleSingleton(),    Component.For<IBackgroundJobConfiguration, BackgroundJobConfiguration>().ImplementedBy<BackgroundJobConfiguration>().LifestyleSingleton(),    Component.For<INotificationConfiguration, NotificationConfiguration>().ImplementedBy<NotificationConfiguration>().LifestyleSingleton(),    Component.For<IEmbeddedResourcesConfiguration, EmbeddedResourcesConfiguration>().ImplementedBy<EmbeddedResourcesConfiguration>().LifestyleSingleton(),    Component.For<IAbpStartupConfiguration, AbpStartupConfiguration>().ImplementedBy<AbpStartupConfiguration>().LifestyleSingleton(),    Component.For<IEntityHistoryConfiguration, EntityHistoryConfiguration>().ImplementedBy<EntityHistoryConfiguration>().LifestyleSingleton(),    Component.For<ITypeFinder, TypeFinder>().ImplementedBy<TypeFinder>().LifestyleSingleton(),    Component.For<IAbpPlugInManager, AbpPlugInManager>().ImplementedBy<AbpPlugInManager>().LifestyleSingleton(),    Component.For<IAbpModuleManager, AbpModuleManager>().ImplementedBy<AbpModuleManager>().LifestyleSingleton(),    Component.For<IAssemblyFinder, AbpAssemblyFinder>().ImplementedBy<AbpAssemblyFinder>().LifestyleSingleton(),    Component.For<ILocalizationManager, LocalizationManager>().ImplementedBy<LocalizationManager>().LifestyleSingleton()    );}

    下一步解析 AbpBootStrapperConfiguration 初始化所有核心模块的配置项。
    之后就是最重要的初始化模块操作了。

    private void LoadAllModules(){Logger.Debug("Loading Abp modules...");List<Type> plugInModuleTypes;// 查找所有模块,封装到 List<Type> 容器var moduleTypes = FindAllModuleTypes(out plugInModuleTypes).Distinct().ToList();Logger.Debug("Found " + moduleTypes.Count + " ABP modules in total.");// 注册模块到 Ioc 容器RegisterModules(moduleTypes);CreateModules(moduleTypes, plugInModuleTypes);_modules.EnsureKernelModuleToBeFirst();_modules.EnsureStartupModuleToBeLast();SetDependencies();Logger.DebugFormat("{0} modules loaded.", _modules.Count);}

    FindAllModuleTypes

    private List<Type> FindAllModuleTypes(out List<Type> plugInModuleTypes){plugInModuleTypes = new List<Type>();// 内部根据[DependsOn]特性来,递归获取所有模块var modules = AbpModule.FindDependedModuleTypesRecursivelyIncludingGivenModule(_modules.StartupModuleType);foreach (var plugInModuleType in _abpPlugInManager.PlugInSources.GetAllModules()){    if (modules.AddIfNotContains(plugInModuleType))    {        plugInModuleTypes.Add(plugInModuleType);    }}return modules;}

    CreateModules

    private void CreateModules(ICollection<Type> moduleTypes, List<Type> plugInModuleTypes){foreach (var moduleType in moduleTypes){    var moduleObject = _iocManager.Resolve(moduleType) as AbpModule;    if (moduleObject == null)    {        throw new AbpInitializationException("This type is not an ABP module: " + moduleType.AssemblyQualifiedName);    }    moduleObject.IocManager = _iocManager;    moduleObject.Configuration = _iocManager.Resolve<IAbpStartupConfiguration>();    // 将模块类型封装到 AbpModule 当中    var moduleInfo = new AbpModuleInfo(moduleType, moduleObject, plugInModuleTypes.Contains(moduleType));    _modules.Add(moduleInfo);    // 设置启动模块    if (moduleType == _modules.StartupModuleType)    {        StartupModule = moduleInfo;    }    Logger.DebugFormat("Loaded module: " + moduleType.AssemblyQualifiedName);}}

    总的来说 CreateModules 的作用就是将之前获取到的模块类型数据再封装为 AbpModuleInfo对象。在 ModuleInfo 对象内部还包括了这个模块所依赖的模块信息。
    构建好所有模块的 ModuleInfo 信息之后,对这个 List<ModuleInfo> 进行排序,将启动模块放在最后,将核心模块放在第一位,具体操作可以参考 _modules.EnsureKernelModuleToBeFirst();_modules.EnsureStartupModuleToBeLast(); 这两个方法。这么做是因为要确保最核心的模块第一位初始化,然后再依次初始化他的子模块。因为是启动模块,所以他是这个依赖树的最低端,留在最后初始化。

    SetDependencies

    遍历 List<ModuleType> 设置每个模块的依赖模块。回到最开始的地方,这里仅仅是初始化模块,之后调用了 StartModules 才是真正的启动模块:

    public virtual void StartModules(){var sortedModules = _modules.GetSortedModuleListByDependency();sortedModules.ForEach(module => module.Instance.PreInitialize());sortedModules.ForEach(module => module.Instance.Initialize());sortedModules.ForEach(module => module.Instance.PostInitialize());}

    启动模块的时候,先按照依赖项来排序,顺序是 Kernal->Module1->Module->2->StartModule。之后从 PreInitialize->Initialize->PostInitialize 这样遍历执行。
    执行完之后所有模块就已经初始化完成了。
    这里可以看到并没有 ShutDown 方法执行,ShutDown 执行的时机是在 AbpBootStrapper 被释放的时候,进行调用。

    public virtual void ShutdownModules(){Logger.Debug("Shutting down has been started");var sortedModules = _modules.GetSortedModuleListByDependency();sortedModules.Reverse();sortedModules.ForEach(sm => sm.Instance.Shutdown());Logger.Debug("Shutting down completed.");}

    不过执行 ShutDown 方法的时候,会将模块列表反转,按照 Start->Module2->Module1->Kernal 这样来关闭。
    模块是 ABP 框架的基础单元,在 ABP 的实现当中模块大部分被当做功能库的形式存在。如果你要使用 ABP 框架的话,必须要定义一个启动模块,不然其他功能是无法正常进行初始化的。

    AbpModule

    public abstract class AbpModule{/// <summary>/// Gets a reference to the IOC manager./// </summary>protected internal IIocManager IocManager { get; internal set; }/// <summary>/// Gets a reference to the ABP configuration./// </summary>protected internal IAbpStartupConfiguration Configuration { get; internal set; }/// <summary>/// Gets or sets the logger./// </summary>public ILogger Logger { get; set; }protected AbpModule(){    Logger = NullLogger.Instance;}/// <summary>/// This is the first event called on application startup. /// Codes can be placed here to run before dependency injection registrations./// </summary>public virtual void PreInitialize(){}/// <summary>/// This method is used to register dependencies for this module./// </summary>public virtual void Initialize(){}/// <summary>/// This method is called lastly on application startup./// </summary>public virtual void PostInitialize(){}/// <summary>/// This method is called when the application is being shutdown./// </summary>public virtual void Shutdown(){}public virtual Assembly[] GetAdditionalAssemblies(){    return new Assembly[0];}/// <summary>/// Checks if given type is an Abp module class./// </summary>/// <param name="type">Type to check</param>public static bool IsAbpModule(Type type){    var typeInfo = type.GetTypeInfo();    return        typeInfo.IsClass &&        !typeInfo.IsAbstract &&        !typeInfo.IsGenericType &&        typeof(AbpModule).IsAssignableFrom(type);}/// <summary>/// Finds direct depended modules of a module (excluding given module)./// </summary>public static List<Type> FindDependedModuleTypes(Type moduleType){    if (!IsAbpModule(moduleType))    {        throw new AbpInitializationException("This type is not an ABP module: " + moduleType.AssemblyQualifiedName);    }    var list = new List<Type>();    if (moduleType.GetTypeInfo().IsDefined(typeof(DependsOnAttribute), true))    {        var dependsOnAttributes = moduleType.GetTypeInfo().GetCustomAttributes(typeof(DependsOnAttribute), true).Cast<DependsOnAttribute>();        foreach (var dependsOnAttribute in dependsOnAttributes)        {            foreach (var dependedModuleType in dependsOnAttribute.DependedModuleTypes)            {                list.Add(dependedModuleType);            }        }    }    return list;}public static List<Type> FindDependedModuleTypesRecursivelyIncludingGivenModule(Type moduleType){    var list = new List<Type>();    AddModuleAndDependenciesRecursively(list, moduleType);    list.AddIfNotContains(typeof(AbpKernelModule));    return list;}private static void AddModuleAndDependenciesRecursively(List<Type> modules, Type module){    if (!IsAbpModule(module))    {        throw new AbpInitializationException("This type is not an ABP module: " + module.AssemblyQualifiedName);    }    if (modules.Contains(module))    {        return;    }    modules.Add(module);    var dependedModules = FindDependedModuleTypes(module);    foreach (var dependedModule in dependedModules)    {        AddModuleAndDependenciesRecursively(modules, dependedModule);    }}}

    在 Abp 模块当中会为你注入一些必须的设施,比如 Ioc 容器,模块配置集合,日志记录器等。
    如果想知道模块如何编写,可以参考 ABP 原有的功能模块实现。

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台