209  
查询码:00001112
ABP框架的模块体系
作者: 潘帅 于 2020年03月03日 发布在分类 / 人防组 / 人防后端 下,并于 2020年03月03日 编辑
ABP 模块

模块Module是ABP框架体系很重要的概念,不同的功能组件包括项目之间都是以模块的形式进行关联的。在ABP框架的启动过程中,模块的遍历、初始化、启动也是很重要的一环。

------------------------

 1.模块的定义


 1.1定义

在ABP框架中定义了基类AbpModule,只要是继承自AbpModule的类就是模块。先来看看这个基类的定义。
namespace Abp.Modules
{
    public abstract class AbpModule
    {
        //获取对IOC管理器的引用
        protected internal IIocManager IocManager { get; internal set; }
        // 获取对ABP配置项的引用
        protected internal IAbpStartupConfiguration Configuration { get; internal set; }
        // 获取或设置日志
        public ILogger Logger { get; set; }

        protected AbpModule()
        {
            Logger = NullLogger.Instance;
        }

        // 预初始化
        public virtual void PreInitialize()
        {
        }

        // 初始化
        public virtual void Initialize()
        {
        }
        
        //初始化后
        public virtual void PostInitialize()
        {

        }

        // 关闭
        public virtual void Shutdown()
        {

        }

        public virtual Assembly[] GetAdditionalAssemblies()
        {
            return new Assembly[0];
        }

        // 检查是否为模块
        public static bool IsAbpModule(Type type)
        {
            var typeInfo = type.GetTypeInfo();
            return
                typeInfo.IsClass &&
                !typeInfo.IsAbstract &&
                !typeInfo.IsGenericType &&
                typeof(AbpModule).IsAssignableFrom(type);
        }

        // 查找依赖模块
        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);
            }
        }
    }
}


在AbpModule中可以看到其内部以接口形式定义了IoC管理器、模块配置项和日志组件,此外还有模块的生命周期事件和查找当前模块所依赖模块的方法。

 1.2生命周期

在AbpModule可以看到模块的四个生命周期事件:

生命周期事件
说明
PreInitialize
预初始化:在初始化之前配置框架和其他模块。能够在依赖注入注册之前,在这个方法中指定需要注入的自定义启动类
Initialize
初始化:一般是来进行依赖注入的注册,常通过 IocManager.RegisterAssemblyByConvention 来实现
PostInitialize
初始化后:用来解析依赖关系
Shutdown
关闭:当应用关闭以后被调用

对于任意一个模块,这四个方法的执行顺序依次为PreInitialize-->Initialize-->PostInitialize-->Shutdown。


 2.模块的依赖


 2.1特性

ABP框架提供了DependsOn属性来显式说明模块间的依赖关系。可以看到DependsOn属性支持的是数组,所以一个模块可以依赖于多个模块。
namespace Abp.Modules
{
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    public class DependsOnAttribute : Attribute
    {
        public Type[] DependedModuleTypes { get; private set; }

        public DependsOnAttribute(params Type[] dependedModuleTypes)
        {
            DependedModuleTypes = dependedModuleTypes;
        }
    }
}

再来看看示例解决方案中各模块的依赖关系。
//Web项目--呈现与分布式服务层
[DependsOn(
    typeof(AbpDemoApplicationModule), 
    typeof(AbpDemoEntityFrameworkCoreModule), 
    typeof(AbpAspNetCoreModule))]
public class AbpDemoWebModule : AbpModule
{
//to do
}

//EntityFrameworkCore项目--基础设施层
[DependsOn(
    typeof(AbpDemoCoreModule), 
    typeof(AbpEntityFrameworkCoreModule))]
public class AbpDemoEntityFrameworkCoreModule : AbpModule
{
// to do
}

//Application项目--应用层
[DependsOn(
    typeof(AbpDemoCoreModule), 
    typeof(AbpAutoMapperModule))]
public class AbpDemoApplicationModule : AbpModule
{
// to do
}

//Core项目--领域层
public class AbpDemoCoreModule : AbpModule
{
// to do
}

 3.模块的启动


 3.1启动顺序

对于每个模块都用同样的生命周期事件,但是有多个模块而且这些模块互相之间存在依赖关系时,这些生命周期事件又该如何执行?对于这种情况,ABP框架作了清晰的定义:所有模块执行完PreInitialize预初始化方法后,所有模块再执行Initialize初始化方法,之后所有模块再执行PostInitialize初始化后方法。在ABP框架的启动过程中也遵循这一流程。
现在再回到AbpBootstrapper的Initialize初始化方法中,仔细查看模块启动的全过程。
   _moduleManager = IocManager.Resolve<AbpModuleManager>();
   _moduleManager.Initialize(StartupModule);
   _moduleManager.StartModules();


3.1.1 实例化模块管理器

 3.1.2 初始化模块管理器
public virtual void Initialize(Type startupModule)
 {
     _modules = new AbpModuleCollection(startupModule);
     LoadAllModules();
 }
 private void LoadAllModules()
 {
     Logger.Debug("Loading Abp modules...");

     List<Type> plugInModuleTypes;
     var moduleTypes = FindAllModuleTypes(out plugInModuleTypes).Distinct().ToList();

     Logger.Debug("Found " + moduleTypes.Count + " ABP modules in total.");

     RegisterModules(moduleTypes);
     CreateModules(moduleTypes, plugInModuleTypes);

     _modules.EnsureKernelModuleToBeFirst();
     _modules.EnsureStartupModuleToBeLast();

     SetDependencies();

     Logger.DebugFormat("{0} modules loaded.", _modules.Count);
 }

##### 3.1.3启动模块
 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());
 }

 3.2 AbpKernelModule


public sealed class AbpKernelModule : AbpModule
{
    public override void PreInitialize()
    {
        //注册过滤器与基础组件
        IocManager.AddConventionalRegistrar(new BasicConventionalRegistrar());

        IocManager.Register<IScopedIocResolver, ScopedIocResolver>(DependencyLifeStyle.Transient);
        IocManager.Register(typeof(IAmbientScopeProvider<>), typeof(DataContextAmbientScopeProvider<>), DependencyLifeStyle.Transient);

        AddAuditingSelectors();
        AddLocalizationSources();
        AddSettingProviders();
        AddUnitOfWorkFilters();
        ConfigureCaches();
        AddIgnoredTypes();
        AddMethodParameterValidators();
        AddDefaultNotificationDistributor();
    }

    public override void Initialize()
    {
        //
        foreach (var replaceAction in ((AbpStartupConfiguration)Configuration).ServiceReplaceActions.Values)
        {
            replaceAction();
        }

        IocManager.IocContainer.Install(new EventBusInstaller(IocManager));

        IocManager.Register(typeof(IOnlineClientManager<>), typeof(OnlineClientManager<>), DependencyLifeStyle.Singleton);
        IocManager.Register(typeof(IOnlineClientStore<>), typeof(InMemoryOnlineClientStore<>), DependencyLifeStyle.Singleton);

        IocManager.Register(typeof(EventTriggerAsyncBackgroundJob<>), DependencyLifeStyle.Transient);

        IocManager.RegisterAssemblyByConvention(typeof(AbpKernelModule).GetAssembly(),
            new ConventionalRegistrationConfig
            {
                InstallInstallers = false
            });
    }

    public override void PostInitialize()
    {
        RegisterMissingComponents();

        IocManager.Resolve<SettingDefinitionManager>().Initialize();
        IocManager.Resolve<FeatureManager>().Initialize();
        IocManager.Resolve<PermissionManager>().Initialize();
        IocManager.Resolve<LocalizationManager>().Initialize();
        IocManager.Resolve<NotificationDefinitionManager>().Initialize();
        IocManager.Resolve<NavigationManager>().Initialize();

        if (Configuration.BackgroundJobs.IsJobExecutionEnabled)
        {
            var workerManager = IocManager.Resolve<IBackgroundWorkerManager>();
            workerManager.Start();
            workerManager.Add(IocManager.Resolve<IBackgroundJobManager>());
        }
    }
  }



 推荐知识

 历史版本

修改日期 修改人 备注
2020-03-03 18:06:41[当前版本] 潘帅 1.0

  目录
    知识分享平台 -V 4.8.7 -wcp