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

返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期html

AbpModule

     在ABP框架中,仓储,服务,这块算是最为重要一块之一了.ABP框架提供了建立和组装模块的基础,一个模块可以依赖于另外一个模块,一个程序集可当作一个模块,数据库

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

       模块的调用每每涉及到前后顺序,若是模块A依赖于模块B,那么模块B要在模块A以前初始化,初始化就至关于注册,如使用IocManager对登记类进行注册,框架

      

    上面这个方法咱们就把MyModule1 注入到MyModule2中了,在调用MyModule2的时候能够初始化MyModule1 .异步

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

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

仓储(repository)

 

     假设咱们有一个应用程序服务,使用仓储(repository)类插入实体到数据库。在这种状况下,应用程序服务类依赖于仓储(repository)类,以下单元测试

      

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

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

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

3,若是将来咱们须要修改UserRepository类,可是UserService依赖于它,这时候,咱们须要修改全部依赖UserRepository的类.

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

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

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

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

UserService服务不须要直接去建立UserRepository.

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

1,UserService依然依赖于UserRepositoryFactory

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

3,测试性仍是很差.

依赖注入

 

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

 

 

 上面就是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,在仓储中能够直接调用,仓储是在领域层和数据映射层的中介,使用相似集合的接口来存取领域对象.

      接口:

 实现:

 

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

 

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

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

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

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

返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期

相关文章
相关标签/搜索