DDD分层为了减少复杂性和提高代码的可重用性,采用分层架构是一种被广泛接受的技术。

为了实现分层的体系结构,ABP遵循DDD(领域驱动设计)的原则,将分为四个层次:

展现层(Presentation):提供一个用户界面,实现用户交互操作。

应用层(Application):进行展现层与领域层之间的协调,协调业务对象来执行特定的应用程序的任务。它不包含业务逻辑。

领域层(Domain):包括业务对象和业务规则,这是应用程序的核心层。

基础设施层(Infrastructure):提供通用技术来支持更高的层。例如基础设施层的仓储(Repository)可通过ORM来实现数据库交互。

根据实际需要,可能会有额外添加的层。例如:

分布式服务层(Distributed Service):用于公开应用程序接口供远程客户端调用。比如通过ASP.NET Web API和WCF来实现。

这些都是常见的以领域为中心的分层体系结构。不同的项目在实现上可能会有细微的差别。

ABP的体系结构

一个简单的解决方案,大致包含5个项目:

每一层可以用一个或多个程序集来实现。

1.领域层(Domain)

领域层就是业务层,是一个项目的核心,所有业务规则都应该在领域层实现。

2.实体(Entity)

实体代表业务领域的数据和操作,在实践中,通过用来映射成数据库表。

3.仓储(Repository)

仓储用来操作数据库进行数据存取。仓储接口在领域层定义,而仓储的实现类应该写在基础设施层。

4.领域服务(Domain service)

当处理的业务规则跨越两个(及以上)实体时,应该写在领域服务方法里面。

5.领域事件(Domain Event)

在领域层某些特定情况发生时可以触发领域事件,并且在相应地方捕获并处理它们。

6.工作单元(Unit of Work)

工作单元是一种设计模式,用于维护一个由已经被修改(如增加、删除和更新等)的业务对象组成的列表。它负责协调这些业务对象的持久化工作及并发问题。

应用层(Application)应用层提供一些应用服务(Application Services)方法供展现层调用。一个应用服务方法接收一个DTO(数据传输对象)作为输入参数,使用这个输入参数执行特定的领域层操作,并根据需要可返回另一个DTO。在展现层到领域层之间,不应该接收或返回实体(Entity)对象,应该进行DTO映射。一个应用服务方法通常被认为是一个工作单元(Unit of Work)。用户输入参数的验证工作也应该在应用层实现。ABP提供了一个基础架构让我们很容易地实现输入参数有效性验证。建议使用一种像AutoMapper这样的工具来进行实体与DTO之间的映射。

基础设施层(Infrastructure)当在领域层中为定义了仓储接口,应该在基础设施层中实现这些接口。可以使用ORM工具,例如EntityFramework或NHibernate。ABP的基类已经提供了对这两种ORM工具的支持。数据库迁移也被用于这一层。

WEB与展现层(Web & Presentation)Web层使用ASP.NET MVC和Web API来实现。可分别用于多页面应用程序(MPA)和单页面应用程序(SPA)。

在SPA中,所有资源被一次加载到客户端浏览器中(或者先只加载核心资源,其他资源懒加载),然后通过AJAX调用服务端WebApi接口获取数据,再根据数据生成HTML代码。不会整个页面刷新。现在已经有很多SPA的JS框架,例如: AngularJs、 DurandalJs、BackboneJs、EmberJs。 ABP可以使用任何类似的前端框架,但是ABP提供了一些帮助类,让我们更方便地使用AngularJs和DurandalJs。

在经典的多页面应用(MPA)中,客户端向服务器端发出请求,服务器端代码(ASP.NET MVC控制器)从数据库获得数据,并且使用Razor视图生成HTML。这些被生成后的HTML页面被发送回客户端显示。每显示一个新的页面都会整页刷新。

SPA和MPA涉及到完全不同的体系结构,也有不同的应用场景。一个管理后台适合用SPA,博客就更适合用MPA,因为它更利于被搜索引擎抓取。

SignalR是一种从服务器到客户端发送推送通知的完美工具。它能给用户提供丰富的实时的体验。

已经有很多客户端的Javascript框架或库,JQuery是其中最流行的,并且它有成千上万免费的插件。使用Bootstrap可以让我们更轻松地完成写Html和CSS的工作。

ABP也实现了根据Web API接口自动创建 Javascript的代码函数,来简化JS对Web Api的调用。还有把服务器端的菜单、语言、设置等生成到JS端。(但是在我自己的项目中,我是把这些自动生成功能关闭的,因为必要性不是很大,而这些又会比较影响性能)。

ABP会自动处理服务器端返回的异常,并以友好的界面提示用户。

ABP模块系统ABP框架提供了创建和组装模块的基础,一个模块能够依赖于另一个模块。在通常情况下,一个程序集就可以看成是一个模块。在ABP框架中,一个模块通过一个类来定义,而这个类要继承自AbpModule。

译者注:如果学习过Orchard的朋友,应该知道module模块的强大了。模块的本质就是可重用性,你可以在任意的地方去调用,而且通过实现模块,你写的模块也可以给别人用。

Assembly程序集:Assembly是一个包含来程序的名称,版本号,自我描述,文件关联关系和文件位置等信息的一个集合。最简单的理解就是:一个你自己写的类库生成的dll就可以看做是一个程序集,这个程序集可以包括很多类,类又包括很多方法等。

.net可以通过反射获取一个程序集中的类以及方法。

下面的例子,我们开发一个可以在多个不同应用中被调用MybolgApplication模块,代码如下:

public class MyBlogApplicationModule : AbpModule //定义

{

public override void Initialize() //初始化

{

IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());

//这行代码的写法基本上是不变的。它的作用是把当前程序集的特定类或接口注册到依赖注入容器中。

}

}

ABP框架会扫描所有的程序集,并且发现AbpModule类中所有已经导入的所有类,如果你已经创建了包含多个程序集的应用,对于ABP,我们的建议是为每一个程序集创建一个Module(模块)。

生命期事件

在一个应用中,abp框架调用了Module模块的一些指定的方法来进行启动和关闭模块的操作。我们可以重载这些方法来完成我们自己的任务。

ABP框架通过依赖关系的顺序来调用这些方法,假如:模块A依赖于模块B,那么模块B要在模块A之前初始化,模块启动的方法顺序如下:

PreInitialize-B

PreInitialize-A

Initialize-B

Initialize-A

PostInitialize-B

PostInitialize-A

下面是具体方法的说明:

1.PreInitialize

预初始化:当应用启动后,第一次会调用这个方法。在依赖注入注册之前,你可以在这个方法中指定自己的特别代码。举个例子吧:假如你创建了一个传统的登记类,那么你要先注册这个类(使用IocManager对登记类进行注册),你可以注册事件到IOC容器。等。

2.Initialize

初始化:在这个方法中一般是来进行依赖注入的注册,一般我们通过IocManager.RegisterAssemblyByConvention这个方法来实现。如果你想实现自定义的依赖注入,那么请参考依赖注入的相关文档。

3.PostInitialize

提交初始化:最后一个方法,这个方法用来解析依赖关系。

4.Shutdown

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

模块依赖(Module dependencies)Abp框架会自动解析模块之间的依赖关系,但是我们还是建议你通过重载GetDependencies方法来明确的声明依赖关系。

[DependsOn(typeof(MyBlogCoreModule))]//通过注解来定义依赖关系

public class MyBlogApplicationModule : AbpModule

{

public override void Initialize()

{

IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());

}

}

例如上面的代码,我们就声明了MyBlogApplicationModule和MyBlogCoreModule的依赖关系(通过属性attribute),MyBlogApplicationModule这个应用模块依赖于MyBlogCoreModule核心模块,并且,MyBlogCoreModule核心模块会在MyBlogApplicationModule模块之前进行初始化。

如何自定义的模块方法我们自己定义的模块中可能有方法被其他依赖于当前模块的模块调用,下面的例子,假设模块2依赖于模块1,并且想在预初始化的时候调用模块1的方法。

public class MyModule1 : AbpModule

{

public override void Initialize() //初始化模块

{

IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());//这里,进行依赖注入的注册。

}

public void MyModuleMethod1()

{

//这里写自定义的方法。

}

}

[DependsOn(typeof(MyModule1))]

public class MyModule2 : AbpModule

{

private readonly MyModule1 _myModule1;

public MyModule2(MyModule1 myModule1)

{

_myModule1 = myModule1;

}

public override void PreInitialize()

{

_myModule1.MyModuleMethod1(); //调用MyModuleMethod1的方法。

}

public override void Initialize()

{

IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());

}

}

就这样,就把模块1注入到了模块2,因此,模块2就能调用模块1的方法了。

abp框架java_ABP框架的体系结构及模块系统讲解相关推荐

  1. [Abp vNext 源码分析] - 2. 模块系统的变化

    一.简要说明 本篇文章主要分析 Abp vNext 当中的模块系统,从类型构造层面上来看,Abp vNext 当中不再只是单纯的通过 AbpModuleManager 来管理其他的模块,它现在则是 I ...

  2. 【ABP框架系列学习】模块系统(4)

    [ABP框架系列学习]模块系统(4) 原文:[ABP框架系列学习]模块系统(4) 0.引言 ABP提供了构建模块和通过组合模块以创建应用程序的基础设施.一个模块可以依赖于另外一个模块.通常,程序集可以 ...

  3. php验证密码后跳转_php-laravel框架用户验证(Auth)模块解析(四)忘记密码

    一.忘记密码模块路由 二.控制器解析 跟注册.登录的控制器一样,大部分的逻辑使用trait引入. ForgotPasswordController:负责忘记密码页面,以及邮件发送 四.扩展开发:自定义 ...

  4. 【Laravel】Laravel-admin后台框架-2创建数据表建立模块增删改查CURD(2)

    前言 前面的操作我们已经能够 安装Laravel-admin 创建数据表并生成模型 修改模型实现按业务写入数据 可以参考之前的文章 [Laravel]Laravel-admin后台框架-2创建数据表建 ...

  5. [golang gin框架] 16.Gin 商城项目-商品模块数据表ER图关系分析

    1.数据表ER图 2.数据表相关 (1).商品分类表相关 1).数据表 -- ---------------------------- -- Table structure for goods_cat ...

  6. 四、Abp Vnext中使用Minio打造文件管理模块(上)

    在Abp商业版本中已经提供了文件管理模块的,免费版本是没有的,本文将介绍如何使用Minio打造一个自己的文件管理模块. 在项目开始之前,需要先安装一个Minio服务,可以在本地pc或云主机中安装,具体 ...

  7. ABP官方文档(三)【模块系统】

    1.3 ABP总体介绍 - 模块系统 1.3.1 ABP模块系统简介 ABP框架提供了创建和组装模块的基础,一个模块能够依赖于另一个模块.在通常情况下,一个程序集就可以看成是一个模块.在ABP框架中, ...

  8. ABP模块系统学习及使用

    ABP模块系统简介 参考: ABP中配置的注册和初始化 ABP模块系统 ABP 源码解析 一. ABP启动 ABP框架提供了创建和组装模块的基础,一个模块能够依赖于另一个模块.在通常情况下,一个程序集 ...

  9. ABP学习实践(十二)--模块系统

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

  10. ABP官方文档翻译 1.3 模块系统

    ABP模块系统 介绍 模块定义 生命周期方法 PreInitialize Initialize PostInitialize Shutdown 模块依赖 插件系统 ASP.NET Core ASP.N ...

最新文章

  1. Windows Updateエラー 80072EE2
  2. Visual Studio 2013或2015工程属性中包含目录和库目录的添加方法,附加依赖项,相对路径
  3. python解释器的工作原理_Python GIL全局解释器锁详解(深度剖析)
  4. STM32-通用定时器-输入捕获
  5. Java元宵趣图_2019元宵节,猪你元宵节快乐
  6. 2021谷饶中学高考成绩查询,2020汕头地理生物中考成绩查询入口
  7. 互评成绩 c语言,1077 互评成绩计算 (C语言)
  8. 【图解】QT 布局、 sizeHint和SizePolicy概念
  9. 在线考试系统详细设计
  10. openresty 网关rsa+aes+redis鉴权解密
  11. 用python画一个机器猫歌词_用Python语言模型和LSTM做一个Drake饶舌歌词生成器
  12. mysql去重汇总_Mysql常用SQL汇总
  13. 阿里大数据之路 总述
  14. 非监督神经网络的wake-sleep算法
  15. 分享几个去图片水印好用的软件给你
  16. 上海大学计算机工程与科学学院院长,李三立
  17. [统计学笔记] 必须要掌握的统计学基本概念和术语(更新中)
  18. 【OpenGL ES】透视变换原理
  19. elasticsearch安装和配置,elasticsearch启动报错:can not run elasticsearch as root
  20. web安全颜色以及微软支持颜色

热门文章

  1. android反编译打包出错,APK打包错误,能解决的给红包!
  2. 答疑解惑:软件定义存储常见问题
  3. 使用自定义文件选择按钮选择文件
  4. Theano入门神经网络(三)
  5. 用C语言做的即时通讯软件,即时通讯软件代码-C语言来编写类似QQ的即时通讯软件求代码!!!...
  6. word文档无法另存为/导出pdf解决办法
  7. spellman斯派曼电源维修XRB100N100K4405
  8. MLA格式Secondary Source引用规范详解
  9. MySQL 读写分离配置实践
  10. 使计算机拒绝远程桌面服务,拒绝通过远程桌面服务登录