ABP - 依赖注入(1)
依赖注入实现了系统之间、模块之间和对象之间依赖关系的解耦,基本上是现代应用程序框架必不可少的一个组成部分。
ABP的依赖注入系统是基于Microsoft的依赖注入扩展库(Microsoft.Extensions.DependencyInjection),所以能够完全兼容.net Core中的依赖注入的用法,同时使用 Autofac 替换了.net Core中的内部容器,利用了Autofac中的一些特性。
Abp依赖注入的配置方式
手动注册依赖注入关系
与Asp.Net Core在Startup类中的ConfigureServices()方法中,通过IServiceCollection向容器中添加依赖注入关系没有区别,在Abp框架中也完成兼容这种方式。
不过这些依赖关系的配置一般会在各自的模块中配置,而不是全部都写在Startup类中,这样使得各个模块之间更加独立,开箱即用。
[DependsOn(typeof(AbpAspNetCoreModule))]
[DependsOn(typeof(SuncereAbpDataModule))]
public class SuncereAbpFreeSqlModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddFreeSql();
}
}
示例中的代码是我们项目中一个ORM模块的依赖注入配置,这是模块基于FreeSql这个ORM框架进行了一层分组,兼容了Abp的工作单元、默认仓储模式。上一篇文章中讲在Abp框架初始化时,会将容器对象在各个模块类中进行传递,context.Services 就是传递过来的IServiceCollection。
按照约定自动注册
除了手动注册的方式之外,Abp框架依赖注入体系的很方便的一个点,就是提供了按照约定的自动依赖注入关系注册。最基本的,在只使用了Volo.Abp核心库的情况下,会将实现了特定接口的类进行注册,根据依赖注入的生命周期,Abp提供了三个接口。
• ITransientDependency 注册为transient生命周期.
• ISingletonDependency 注册为singleton生命周期.
• IScopedDependency 注册为scoped生命周期.
这些接口,都是空接口,起到标记的作用。这种设计方式,在微软的代码和很多框架中都很常见。
通过对源码的研究,可以发现这其实是Abp提供了一个约定注册器接口IConventionalRegistrar,并且Abp提供了实现默认的实现。并且在Abp引擎初始化的时候,将所有的模块程序集遍历了一遍,将其中满足约定的类进行了依赖注入注册。
查看自动依赖注入源码的入口点,其实就在上篇文章中提到的Abp引擎初始化过程中,AbpApplicationBase构造函数中调用的AddCoreAbpServices()方法中,其中的services.AddAssemblyOf<IAbpApplication>()是关键。

可以看到,这里向集合中添加了默认预定注册器,并且通过规则进行依赖注入注册。那么规则注册器是如何查找程序集中的类,并且注册依赖关系的呢?



这里就看到了上面提到的三个接口了,但是从这里可以看出,这三个接口只是提供了生命周期的信息,但是依赖注入的注册,除了生命周期,还有类与接口的对应关系。

通过对DefaultConventionalRegistrar、ConventionalRegistrarBase、ExposedServiceExplorer、ExposeServicesAttribute代码的查看,可以明白Abp默认的依赖关系注册是怎么样的,以及它是怎么实现的。
默认规则注册:
1)实现了ITransientDependency等三个接口的公开、非泛型类,会被注册到容器中。
2)如果这个类实现了其他接口,并且这个接口和类之间的命名符合规则,接口和类的关系会被注册到容器中。
例如
public class BookRepository: IRepository, IBookRepository, IBookStore, ITransientDependency
{
}
上面的代码中,BookRepository在容器中是可以找到三个依赖关系配置的。
除了默认规则注册之外,Abp还在其他模块中提供了其他的注册规则,如Volo.Abp.AspNetCore.Mvc模块中的AbpAspNetCoreMvcConventionalRegistrar、Volo.Abp.AspNetCore.Components中的AbpWebAssemblyConventionalRegistrar等。
Abp框架固有的注册类型
一些特定类型会默认注册到依赖注入.例子:
• 模块类注册为singleton.
• MVC控制器(继承Controller或AbpController)被注册为transient.
• MVC页面模型(继承PageModel或AbpPageModel)被注册为transient.
• MVC视图组件(继承ViewComponent或AbpViewComponent)被注册为transient.
• 应用程序服务(实现IApplicationService接口或继承ApplicationService类)注册为transient.
• 存储库(实现IRepository接口)注册为transient.
• 域服务(实现IDomainService接口)注册为transient.
我们也可以通过实现自己的依赖注入注册规则,只需要实现IConventionalRegistrar接口,并在模块类中的PreConfigureServices()方法中将其添加到ConventionalRegistrarList中。
通过特性注册
从上面的源码中也可以看出,Abp框架也支持通过特性的方式声明依赖注入关系的,而且特性的声明方式会优先于默认约定的方式。
我们可以用 DependencyAttribute 声明依赖注入的生命周期和注入的方式,ExposeServicesAttribute 声明类和接口之间的对应关系。ExposeServicesAttribute 就是 IExposedServiceTypesProvider 的实现类。
特别注意的,在声明了ExposeServicesAttribute,并且未设置IncludeDefaults、IncludeSelf 的值的情况下,由于默认值的关系,这两个值会是false,即默认约定不起作用了,该类注册为ExposeServicesAttribute中指定的接口的实现。 当然ExposeServicesAttribute可以指定多个接口。
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
[ExposeServices(typeof(IBookRepository))]
public class BookRepository: IRepository, IBookRepository, IBookStore
{
}
泛型类的注册
通过源码可以知道,无论是按照约定自动注册,还是通过特性的方式进行注册,都是无法注册泛型类的依赖注入关系的,泛型类的依赖注入关系只能够通过手动注册的方式注入。
context.service.AddTransient<IRepository<,>, Repository<,>>();
通过以上方式可以注册泛型类的依赖注入关系,<> 中一个,表示该类有两个泛型类型。
以上是依赖注入配置部分的内容,这里拆成了两篇,避免文章太长大家阅读不适
ABP 系列总结:
目录:ABP 系列总结
上一篇:ABP - 模块加载机制
ABP - 依赖注入(1)的更多相关文章
- ABP(现代ASP.NET样板开发框架)系列之6、ABP依赖注入
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之6.ABP依赖注入 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...
- 基于DDD的.NET开发框架 - ABP依赖注入
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- ABP依赖注入
ABP依赖注入 点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之6.ABP依赖注入 ABP是“ASP.NET Boilerplate Project (ASP.N ...
- 3. abp依赖注入的分析.md
abp依赖注入的原理剖析 请先移步参考 [Abp vNext 源码分析] - 3. 依赖注入与拦截器 本文此篇文章的补充和完善. abp的依赖注入最后是通过IConventionalRegister接 ...
- ABP 依赖注入
1.ABP自动注入 //IapplicationService注入方式暴露接 //ITransientDependency 不会暴露接口 ITransientDependency和ISingleton ...
- abp 依赖注入声明
public class SchedulerManager : ISingletonDependency { private ILogger logger; public SchedulerManag ...
- ABP框架 - 依赖注入
文档目录 本节内容: 什么是依赖注入 传统方式的问题 解决方案 构造器注入模式 属性注入模式 依赖注入框架 ABP 依赖注入基础 注册依赖 约定注入 辅助接口 自定义/直接 注册 使用IocManag ...
- (译)ABP之依赖注入
原文地址:https://aspnetboilerplate.com/Pages/Documents/Dependency-Injection 什么是依赖注入 传统方式的问题 解决方案 构造函数注入 ...
- ABP官方文档翻译 2.1 依赖注入
依赖注入 什么是依赖注入 传统方式的问题 解决方案 构造函数注入模式 属性注入模式 依赖注入框架 ABP依赖注入基础设施 注册依赖注入 传统注册 帮助接口 自定义/直接注册 使用IocManager ...
- ASP.NET Core - 依赖注入(四)
4. ASP.NET Core默认服务 之前讲了中间件,实际上一个中间件要正常进行工作,通常需要许多的服务配合进行,而中间件中的服务自然也是通过 Ioc 容器进行注册和注入的.前面也讲到,按照约定中间 ...
随机推荐
- Spring--案例:百度网盘密码数据兼容处理
案例再度来袭 也就是说,在百度网盘的密码复制时,后面即使有空格也能提取成功(trim方法) 案例的实现: 也就是实现存在空格时,也能输出true: 现在的话: 那么,我们应该如何使得它忽略空格呢? 这 ...
- Javaweb基础复习------Filter相关应用+登录验证案例的使用
Filter(过滤器) 基本步骤: 1.定义类,实现Filter接口,并重写其所有方法 2.配置Filter拦截资源的路径,在类上定义2 WebFilter注解(WebFilter配置的路径,是拦截资 ...
- 熹乐科技范维肖CC:基于开源 YoMo 框架构建“全球同服”的 Realtime Metaverse Application
前言 在「RTE2022 实时互联网大会」中,熹乐科技创始人 & CEO @范维肖CC 以<基于开源 YoMo 框架构建"全球同服"的 Realtime Metave ...
- 最简单的for循环语句
前言 在前面的文章中,壹哥给大家讲解了顺序结构.分支结构,接下来我们就来学习Java里的循环结构.Java里的循环结构,可以通过while.do-while.for.foreach等方式进行实现,今天 ...
- PyQt5学习 (2)--QWidget(上)
描述: 1.所有可视控件的基类 2.是一个最简单的空白控件 3.控件时用户界面的最小元素:接收各种事件.绘制在桌面上,展示给用户看 4.每个控件都是矩形的,它们按Z轴顺序排序 5. ...
- Dubbo服务提供者如何优雅升级?
文章首发于公众号:BiggerBoy.欢迎关注. 往期文章推荐 大坑!隐式转换导致索引失效...高性能分布式限流:Redis+Lua真香!MySQL索引知识点&常见问题汇总联合索引在B+树上的 ...
- 二进制安装Kubernetes(k8s) v1.26.0 IPv4/IPv6双栈
二进制安装Kubernetes(k8s) v1.26.0 IPv4/IPv6双栈 https://github.com/cby-chen/Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 ...
- [Linux]常用命令之【source|export/env】#点命令/环境变量#
1 source 1-1 source 命令概述 source命令用法:source FileName 简述 source命令(从 C Shell 而来)是bash shell的内置命令. sourc ...
- 6.理解Jwt代码
1.昨天主要是对Jwt的代码里面不熟悉的代码进行了简要的理解,发现其实有些流程并不是普通程序员自己写的,而是自己进行拓展,这些流程是开源程序员写的开发流程:我发现这些代码一般要么是父类的方法实现,要么 ...
- mysql迁移:mysqldump导出表结构及数据
问题描述:有需要mysql某几张表的需求,某个数据库某几张表,导出先检查相应的数据库和表是否存在 数据泵用法:默认导出的是表结构以及表中的数据 mysqldump -uroot -p -S /data ...