ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入

时间:2023-01-16 07:43:29

在ABP框架中,仓储,服务,这块算是最为重要一块之一了.ABP框架提供了创建和组装模块的基础,一个模块能够依赖于另一个模块,一个程序集可看成一个模块,

一个模块可以通过一个类来定义这个模块,而给定义这个类要继承自已经疯转好的AbpModule..net通过反射来获取这些程序集中的类或者方法

       模块的调用往往涉及到先后顺序,如果模块A依赖于模块B,那么模块B要在模块A之前初始化,初始化就相当于注册,如使用IocManager对登记类进行注册,

ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入

上面这个方法我们就把MyModule1 注入到MyModule2中了,在调用MyModule2的时候可以初始化MyModule1 .

什么是依赖注入呢?百科是这样说:“依赖注入是一种软件设计模式,一个或多个依赖项(或服务)被注入或通过引用传递到一个依赖对象,并且成为客户端状态的一部分。这种模式把客户端依赖项的创建从它自己的行为中分离出来,允许程序设计成松耦合的,遵循依赖倒置和单一职责的原则。和服务定位器模式相比,它允许客户端知道他们使用的系统查找依赖项。”

不使用依赖注入技术,很难管理依赖项和发布一个结构良好的应用。

假设我们有一个应用程序服务,使用仓储(repository)类插入实体到数据库。在这种情况下,应用程序服务类依赖于仓储(repository)类,如下

ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入

UserService使用UserRepository插入Person到数据库。但是这段代码有一些问题:

1,服务层UserService通过接口IUserRepository调用CreatePerson实现新增一个User对象,看似调用了IUserRepository接口,但是实际上还是依赖于仓促层的UserRepository.

2,UserService通过IUserRepository创建对象的时候,实际上new一个UserRepository区实现,这与直接调用UserRepository无差别,IUserRepository失去存在的意义.

3,如果未来我们需要修改UserRepository类,但是UserService依赖于它,这时候,我们需要修改所有依赖UserRepository的类.

4,有了这样的依赖,很难对UserService进行单元测试。

5,与"高内聚低耦合"的的原则背道而驰,这里可以看到服务层与仓储层有依赖.

为了解决这些问题于是就有了下面这个版本.

ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入

这就是工厂模式,实际上在abp之前我也经常用这种方式,非常繁琐,搭框架老是出错,UserRepositoryFactory是一个静态类,创建并返回一个IUserRepository

UserService服务不需要直接去创建UserRepository.

这种方法虽然可以,但是依然存在一些问题.

1,UserService依然依赖于UserRepositoryFactory

2,每一个仓储都有写一个工厂,很繁琐.

3,测试性还是不好.

解决办法有几种,包括属性注入,构造函数注入,和依赖注入框架等等.

ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入

上面就是abp中构造函数注入与属性输入的完美运用.现在,UserService不知道哪些类实现userRepository以及如何创建它。谁需要使用UserService,首先创建一个IUserServiceUserService并将其传递给构造函数就可以了.

有人可能说userRepository的从属类里面可能存在依赖,依赖注入框架自动化管理依赖关系都已经解决了这些问题.构造函数注入模式是一个完美的提供类的依赖关系的方式。通过这种方式,你不能创建类的实例,而不提供依赖项。它也是一个强大的方式显式地声明是什么类的需求正确地工作。

但是,在某些情况下,该类依赖于另一个类,但也可以没有它。这通常是适用于横切关注点(如日志记录)。一个类可以没有工作日志,但它可以写日志如果你提供一个日志对象。在这种情况下,您可以定义依赖为公共属性,而不是让他们放在构造函数,上面例子中NullLogger.Instance 是一个单例对象,实现了ILogger接口,但实际上什么都没做(不写日志。它实现了ILogger实例,且方法体为空),在我们需要写日志的地方,我们只需要UserService.Logger = new Log4NetLogger();如此,我们就可以写入日志了,如果不写就不调用,因此是一个可选的依赖.

几乎所有的依赖注入框架都支持属性注入模式

ABP的依赖注入基于 Castle Windsor框架。Castle Windsor最成熟的DI框架之一。依赖注入的框架还有好多,如Unity,Ninject,StructureMap,Autofac等,之前我用过Unity其他的几个没有研究过,依赖框架都可以自动解决依赖关系。他们可以创建所有依赖项(递归地依赖和依赖关系)。所以你只需要根据注入模式写类和类构造函数&属性,其他的交给DI框架处理!在良好的应用程序中,类甚至独立于DI框架。整个应用程序只会有几行代码或类,显示的与DI框架交互。

有人说上面这个例子看不出来依赖注入啊,其实这里UserService是继承自IUserService,而IUserService继承自IApplicationService,abp在IApplicationService封装了很多东西,ABP会自动注册它,因为它实现IApplicationService接口(它只是一个空的接口)。它会被注册为transient (每次使用都创建实例)。当你注入(使用构造函数注入)IUserService接口成一个类,UserService对象会被自动创建并传递给构造函数。

命名约定在这里非常重要。例如你可以将名字PersonAppService改为 MyPersonAppService或另一个包含“PersonAppService”后缀的名称,由于IPersonAppService包含这个后缀。但是你可以不遵循PeopleService命名您的服务类。如果你这样做,它将不会为IPersonAppService自动注册(它需要自注册(self-registration)到DI框架,而不是接口),所以,如果你想要你应该手动注册它.

仓储

    上一章我们已经定义实体类,和DTOs,在仓储中可以直接调用,仓储是在领域层和数据映射层的中介,使用类似集合的接口来存取领域对象.

接口:ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入

实现:

ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入

在例子中IRepository继承自abp已经封装好的IRepository<TEntity>中,在IRepository<TEntity>中已经为我们封装好了许多方法,这就省得我们在为每一个仓储创建不同的方法了,这点很好如下图.

ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入

包含了各式各样的方法,如增删查改等方法.还有一些Async的异步方法.GetAll返回IQueryable<T>类型的对象。因此我们可以在调用完这个方法之后进行Linq操作.

现在项目中运用的是EF框架,所以如果ORM框架没有提供Async的仓储方法则它会以同步的方式操作。同样地,举例来说,InsertAsync操作起来和EF的新增是一样的,因为EF会直到单元作业(unit of work)完成之后才会写入新实体到数据库中(DbContext.SaveChanges)。

数据库连接的开启和关闭,在仓储方法中,ABP会自动化的进行连接管理.当仓储方法被调用后,数据库连接会自动开启且启动事务。当仓储方法执行结束并且返回以后,所有的实体变化都会被储存, 事务被提交并且数据库连接被关闭,一切都由ABP自动化的控制。如果仓储方法抛出任何类型的异常,事务会自动地回滚并且数据连接会被关闭。上述所有操作在实现了IRepository接口的仓储类所有公开的方法中都可以被调用。如果仓储方法调用其它仓储方法(即便是不同仓储的方法),它们共享同一个连接和事务。连接会由仓储方法调用链最上层的那个仓储方法所管理。

另外所有的仓储对象都是暂时性的。这就是说,它们是在有需要的时候才会被创建。ABP大量的使用依赖注入,当仓储类需要被注入的时候,新的类实体会由注入容器会自动地创建.

ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入的更多相关文章

  1. ABP&plus;AdminLTE&plus;Bootstrap Table权限管理系统第五节--WBEAPI及SwaggerUI

    一,Web API ABP的动态WebApi实现了直接对服务层的调用(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 调用没 ...

  2. ABP&plus;AdminLTE&plus;Bootstrap Table权限管理系统第六节--abp控制器扩展及json封装

    一,控制器AbpController 说完了Swagger ui 我们再来说一下abp对控制器的处理和json的封装. 首先我们定义一个控制器,在新增控制器的时候,控制器会自动继承自AbpContro ...

  3. ABP&plus;AdminLTE&plus;Bootstrap Table权限管理系统第六节--abp控制器扩展及json封装以及6种处理时间格式化的方法

    返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 一,控制器AbpController 说完了Swagger ui 我们再来说一下abp对控制器的处理和json的封 ...

  4. ABP&plus;AdminLTE&plus;Bootstrap Table权限管理系统第十一节--bootstrap table之用户管理列表

    这张开始bootstrap table,引入项目有两种方法,一种是直接去官网下载 地址:http://bootstrap-table.wenzhixin.net.cn/ 另一种是Nuget引入. 然后 ...

  5. ABP&plus;AdminLTE&plus;Bootstrap Table权限管理系统第十节--AdminLTE模板菜单处理

    上节我们把布局页,也有的临时的菜单,但是菜单不是应该动态加载的么?,所以我们这节来写菜单.首先我们看一下AdminLTE源码里面的菜单以及结构. <aside class="main- ...

  6. ABP&plus;AdminLTE&plus;Bootstrap Table权限管理系统第七节--登录逻辑及abp封装的Javascript函数库

    经过前几节,我们已经解决数据库,模型,DTO,控制器和注入等问题.那么再来看一下登录逻辑.这里算是前面几节的一个初次试水. 首先我们数据库已经有的相应的数据. 模型和DTO已经建好,所以我们直接在服务 ...

  7. ABP&plus;AdminLTE&plus;Bootstrap Table权限管理系统第十一节--Bootstrap Table用户管理列表以及Module Zero之用户管理

    返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 用户实体 用户实体代表应用的一个用户,它派生自AbpUser类,如下所示: public class User : ...

  8. ABP&plus;AdminLTE&plus;Bootstrap Table权限管理系统第七节--登录逻辑及几种abp封装的Javascript函数库

    返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期         简介 经过前几节,我们已经解决数据库,模型,DTO,控制器和注入等问题.那么再来看一下登录逻辑.这 ...

  9. ABP&plus;AdminLTE&plus;Bootstrap Table权限管理系统一期

       学而时习之,不亦说乎,温顾温知新,可以为师矣. 这也是算是一种学习的方法和态度吧,经常去学习和总结,在博客园看了很多大神的文章,写下一点对于ABP(ABP是“ASP.NET Boilerplat ...

随机推荐

  1. ABP文档 - 审计日志

    文档目录 本节内容: 简介 关于 IAuditingStore 配置 通过特性启用/禁用 注意 简介 *:“一个审计追踪(也叫审计日志)是一个安全相关的时序记录.记录组.和/或记录源和目标,作为 ...

  2. Curator Zookeeper分布式锁

    Curator Zookeeper分布式锁 pom.xml中添加如下配置 <!-- https://mvnrepository.com/artifact/org.apache.curator/c ...

  3. Python自动化 【第九篇】:Python基础-线程、进程及python GIL全局解释器锁

    本节内容: 进程与线程区别 线程 a)  语法 b)  join c)  线程锁之Lock\Rlock\信号量 d)  将线程变为守护进程 e)  Event事件 f)   queue队列 g)  生 ...

  4. &lbrack;C&plus;&plus;&rsqb;C&plus;&plus;标准里 string和wstring

    typedef basic_string<char> string; typedef basic_string<wchar_t> wstring; 前者string是常用类型, ...

  5. RGB颜色二值化

    原理:RGB颜色根据计算'灰度'的公式,可以转化为黑白2种颜色,实现二值化. 业务场景的应用:可以根据背景颜色,取一个黑色或白色的颜色,作为背景色上的文案字体颜色 具体代码: function get ...

  6. Spring Filter components in auto scanning

    In this Spring auto component scanning tutorial, you learn about how to make Spring auto scan your c ...

  7. cookie会话技术

    会话技术 B/S请求是无状态无记忆的,脚本与脚本之间是没有联系的,导致不能进行连续的业务逻辑 Cookie技术:将会话数据保存在浏览器端 原理:服务器向浏览器发送指令,用来管理存储在浏览器端的cook ...

  8. CMake set 语法

    参考CMake官方文档:https://cmake.org/cmake/help/v3.14/command/set.html 1. 普通变量 set(<variable> <val ...

  9. IIS 域名 带参数 设置重定向

    IIS里面设置重定向后,经常会出现,从百度快照里直接打不开的情况. 可以在IIS里面设置重定向的时候,把参数加上,格式如下: http://www.***.com%S%Q

  10. Error&colon; Cannot find module &&num;39&semi;internal&sol;fs&&num;39&semi;

    $ sudo n 6.9.1 $ sudo npm -g install npm@next $ sudo n stable curl -0 -L https://npmjs.org/install.s ...