什么是Module?

Module就是模块化的设计思想。开发人员可以将自定义的功能以模块的形式集成到项目中。具体的功能也可以设计成一个单独的模块

AbpModule

AbpModule是所有Module的基类。

ABP如何发现Moudle

1. 程序入口调用:AbpBootstrapper.Initialize()

2. 通过入口的Moudle获取到所有互相依赖的Moudle

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);
}
} /// <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;
}

3. 注册所有Moudle

RegisterModules(moduleTypes);

4. 创建所有Module的描述信息

CreateModules(moduleTypes, plugInModuleTypes);
  • AbpModule的基本信息放在AbpModuleInfo类中
  • 多个AbpModuleInfo放在AbpModuleCollection集合中

5. 初始化所有Moudle

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());
}

由于模块有依赖关系存在,所以初始化之前确定好初始化顺序,即:被依赖的模块要在依赖的模块之前初始化

至此所有Moudle都被Abp框架集成了

如何把自己Moudle中的类和接口注册到abp框架中

比如AbpWebMvcModule这个模块,就是如何把Controller注册到Abp框架中

每个模块都有PreInitialize 和 Initialize方法

  1. 在PreInitialize添加依赖关系
  2. 在Initialize替换ControllerFactory
/// <summary>
/// This module is used to build ASP.NET MVC web sites using Abp.
/// </summary>
[DependsOn(typeof(AbpWebModule))]
public class AbpWebMvcModule : AbpModule
{
/// <inheritdoc/>
public override void PreInitialize()
{
//添加依赖关系
IocManager.AddConventionalRegistrar(new ControllerConventionalRegistrar()); IocManager.Register<IAbpMvcConfiguration, AbpMvcConfiguration>(); Configuration.ReplaceService<IAbpAntiForgeryManager, AbpMvcAntiForgeryManager>();
} /// <inheritdoc/>
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
//用WindsorControllerFactory替换MVC下默认的ControllerFactory
//MVC将使用WindsorControllerFactory从IOC容器中解析出controller
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(IocManager));
HostingEnvironment.RegisterVirtualPathProvider(IocManager.Resolve<EmbeddedResourceVirtualPathProvider>());
}
}

依赖关系表明:注册所有Controller

/// <summary>
/// Registers all MVC Controllers derived from <see cref="Controller"/>.
/// </summary>
public class ControllerConventionalRegistrar : IConventionalDependencyRegistrar
{
/// <inheritdoc/>
public void RegisterAssembly(IConventionalRegistrationContext context)
{
//注册所有Controller
context.IocManager.IocContainer.Register(
Classes.FromAssembly(context.Assembly)
.BasedOn<Controller>()
.If(type => !type.GetTypeInfo().IsGenericTypeDefinition)
.LifestyleTransient()
);
}
}

WindsorControllerFactory将替代DefaultControllerFactory

从IOC容器中解析出Controller

/// <summary>
/// This class is used to allow MVC to use dependency injection system while creating MVC controllers.
/// </summary>
public class WindsorControllerFactory : DefaultControllerFactory
{
/// <summary>
/// Reference to DI kernel.
/// </summary>
private readonly IIocResolver _iocManager; /// <summary>
/// Creates a new instance of WindsorControllerFactory.
/// </summary>
/// <param name="iocManager">Reference to DI kernel</param>
public WindsorControllerFactory(IIocResolver iocManager)
{
_iocManager = iocManager;
} /// <summary>
/// Called by MVC system and releases/disposes given controller instance.
/// </summary>
/// <param name="controller">Controller instance</param>
public override void ReleaseController(IController controller)
{
_iocManager.Release(controller);
} /// <summary>
/// Called by MVC system and creates controller instance for given controller type.
/// </summary>
/// <param name="requestContext">Request context</param>
/// <param name="controllerType">Controller type</param>
/// <returns></returns>
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
return base.GetControllerInstance(requestContext, controllerType);
} return _iocManager.Resolve<IController>(controllerType);
}
}

模块的生命周期

1. PreInitialize

初始化之前:当应用启动后会首先调用这个方法,在依赖注入之前。

2. Initialize

初始化:这个方法一般是用来依赖注入的,一般调用IocManager.RegisterAssemblyByConvention实现。

3. PostInitialize

用来解析依赖关系。

4. Shutdown

当应用关闭以后,这个方法会被调用。

模块依赖

Abp框架会自动解析模块之间的依赖关系

[DependsOn(typeof(AbpWebCommonModule))]
public class AbpWebModule : AbpModule
{
/// <inheritdoc/>
public override void Initialize()
{
//依赖注入
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}

AbpWebModule依赖于AbpWebCommonModule,AbpWebCommonModule会在AbpWebModule之前初始化

这两个模块启动的顺序为:

AbpWebCommonModule.PreInitialize();
AbpWebModule.PreInitialize(); AbpWebCommonModule.Initialize();
AbpWebModule.Initialize(); AbpWebCommonModule.PostInitialize();
AbpWebModule.PostInitialize();

ABP先完成所有Module的PreInitialize,接着再执行所有Module的Initialize,最后执行PostInitialize。不是执行完一个Module的这三个方法,再去执行下一个Module的这三个方法

调用依赖模块

在AbpWebModule中如何调用AbpWebCommonModule中的方法?

在AbpWebModule中:

private readonly abpWebCommonModule _abpWebCommonModule;

public AbpWebModule(AbpWebCommonModule abpWebCommonModule)
{
_abpWebCommonModule = abpWebCommonModule;
} public override void PreInitialize()
{
//调用abpWebCommonModule中的方法。
//_abpWebCommonModule.
}

abp底层框架的一些功能模块如何注册?

底层的模块都会依赖于AbpKernelModule,AbpKernelModule中主要初始化各种拦截器,如审计日志、多语言、工作单元拦截器等。

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();
}

Reference

ABP源码分析三:ABP Module

ABP-Module的更多相关文章

  1. Spring Boot Starter 和 ABP Module

    Spring Boot 和 ABP 都是模块化的系统,分别是Java 和.NET 可以对比的框架.模块系统是就像乐高玩具一样,一块一块零散积木堆积起一个精彩的世界.每种积木的形状各不相同,功能各不相同 ...

  2. ABP源码分析三:ABP Module

    Abp是一种基于模块化设计的思想构建的.开发人员可以将自定义的功能以模块(module)的形式集成到ABP中.具体的功能都可以设计成一个单独的Module.Abp底层框架提供便捷的方法集成每个Modu ...

  3. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  4. ABP 索引

    官方网站 Github ABP集合贴 @ kebinet https://www.codeproject.com/articles/1115763/using-asp-net-core-entity- ...

  5. ABP模块化

    基于Abp模块化.插件化的设计,开发人员可以将自定义的功能以模块的形式集成到项目中. 模块的加载 模块: 插件: 模块及插件的加载路线: 1. 扩展的HttpApplication对象(在Abp.We ...

  6. ABP之模块分析

    本篇作为我ABP介绍的第三篇文章,这次想讲下模块的,ABP文档已经有模块这方面的介绍,但是它只讲到如何使用模块,我想详细讲解下它模块的设计思路. ABP 框架提供了创建和组装模块的基础,一个模块能够依 ...

  7. ABP之模块

    ABP的反射 为什么先讲反射,因为ABP的模块管理基本就是对所有程序集进行遍历,再筛选出AbpModule的派生类,再按照以来关系顺序加载. ABP对反射的封装着重于程序集(Assembly)与类(T ...

  8. 基于DDD的.NET开发框架 - ABP模块设计

    返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...

  9. ABP模块设计

    ABP模块设计 返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术 ...

  10. ABP入门系列(15)——创建微信公众号模块

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1. 引言 现在的互联网已不在仅仅局限于网页应用,IOS.Android.平板.智能家居等平台正如 ...

随机推荐

  1. [最短路]P1828 香甜的黄油 Sweet Butter

    题目描述 农夫John发现做出全威斯康辛州最甜的黄油的方法:糖.把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油.当然,他将付出额外的费 ...

  2. 深入了解Android蓝牙Bluetooth——《基础篇》

    什么是蓝牙?   也可以说是蓝牙技术.所谓蓝牙(Bluetooth)技术,实际上是一种短距离无线电技术,是由爱立信公司公司发明的.利用"蓝牙"技术,能够有效地简化掌上电脑.笔记本电 ...

  3. jstl--->Core 核心标签库->流程控制

    jstl--->Core 核心标签库->流程控制 -->if.choose.when.otherwise  <c:if>条件判断 语法1:没有本体内容  <c:if ...

  4. 解决tomcat部署包错误

    Context namespace element 'annotation-config' and its parser class [org.springframework.context.anno ...

  5. C++ vector 常用API

    vector: 向量容器,动态数组,类模板 定义和初始化: vector<T> v1; //v1是空vector,元素类型是T类型,执行默认初始化,int为0,string为空串 vect ...

  6. Python爬虫(十五)_案例:使用bs4的爬虫

    本章将从Python案例讲起:所使用bs4做一个简单的爬虫案例,更多内容请参考:Python学习指南 案例:使用BeautifulSoup的爬虫 我们已腾讯社招页面来做演示:http://hr.ten ...

  7. JavaScript中对日期格式化的新想法.

    其实我们对与日期的显示,也就那么几种,不需要每次都传格式化字符串. 只要告诉函数你想要什么结果就好了,以下是在ios的JavaScript中我新写的日期格式化函数: /** 格式化日期 @param ...

  8. 【LDA】修正 GibbsLDA++-0.2 中的两个内存问题

    周末这两天在家用LDA做个小实验. 在LDA的众多实现的工具包中.GibbsLDA 是应用最广泛的.包含c++版本号.java版本号等.GibbsLDA++ 是它的C++版本号的实现.眼下最新版本号是 ...

  9. 把握linux内核设计思想(十三):内存管理之进程地址空间

    [版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet.文章仅供学习交流,请勿用于商业用途] 进程地址空间由进程可寻址的虚拟内存组成,Linux 的虚拟地址空间为0~4G字 ...

  10. CNN中的卷积操作的参数数计算

    之前一直以为卷积是二维的操作,而到今天才发现卷积其实是在volume上的卷积.比如输入的数据是channels*height*width(3*10*10),我们定义一个核函数大小为3*3,则输出是8* ...