- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
依赖注入实现了系统之间、模块之间和对象之间依赖关系的解耦,基本上是现代应用程序框架必不可少的一个组成部分.
ABP的依赖注入系统是基于Microsoft的依赖注入扩展库(Microsoft.Extensions.DependencyInjection),所以能够完全兼容.net Core中的依赖注入的用法,同时使用 Autofac 替换了.net Core中的内部容器,利用了Autofac中的一些特性.
与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-依赖注入(1)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试测试依赖于其他服务 authService 的服务 documentViewer angular .module('someModule') .service('docu
如果我的网站上线(不要认为它会,目前它只是一个学习练习)。 我一直在使用 mysql_real_escape_string();来自 POST、SERVER 和 GET 的数据。另外,我一直在使用 i
我有以下代码,它容易受到 SQL 注入(inject)的攻击(我认为?): $IDquery = mysqli_query($connection, "SELECT `ID` FROM users W
我一直在自学如何创建扩展,以期将它们用于 CSS 注入(inject)(以及最终以 CSS 为载体的 SVG 注入(inject),但那是以后的问题)。 这是我当前的代码: list .json {
这个简单的代码应该通过 Java Spring 实现一个简单的工厂。然而结果是空指针,因为 Human 对象没有被注入(inject)对象(所以它保持空)。 我做错了什么? 谢谢 配置 @Config
我正在编写一个 ASP.NET MVC4 应用程序,它最终会动态构建一个 SQL SELECT 语句,以便稍后存储和执行。动态 SQL 的结构由用户配置以用户友好的方式确定,具有标准复选框、下拉列表和
首先让我说我是我为确保 SQL 注入(inject)攻击失败而采取的措施的知己。所有 SQL 查询值都是通过事件记录准备语句完成的,所有运算符(如果不是硬编码)都是通过数字白名单系统完成的。这意味着如
这是 SQL 映射声称可注入(inject)的负载: user=-5305' UNION ALL SELECT NULL,CONCAT(0x716b6b7071,0x4f5577454f76734
我正在使用 Kotlin 和 Android 架构组件(ViewModel、LiveData)构建一个新的 Android 应用程序的架构,并且我还使用 Koin 作为我的依赖注入(inject)提供
假设 RequestScope 处于 Activity 状态(使用 cdi-unit 的 @InRequestScope) 给定 package at.joma.stackoverflow.cdi;
我有一个搜索表单,可以在不同的提供商中搜索。 我从拥有一个基本 Controller 开始 public SearchController : Controller { protected r
SQLite 注入 如果您的站点允许用户通过网页输入,并将输入内容插入到 SQLite 数据库中,这个时候您就面临着一个被称为 SQL 注入的安全问题。本章节将向您讲解如何防止这种情况的发生,确保脚
我可以从什么 dll 中获得 Intercept 的扩展?我从 http://github.com/danielmarbach/ninject.extensions.interception 添加了
使用 NInject 解析具有多个构造函数的类似乎不起作用。 public class Class1 : IClass { public Class1(int param) {...} public
我有一个 MetaManager 类: @Injectable() export class MetaManager{ constructor(private handlers:Handler
我是 Angular 的新手,我不太清楚依赖注入(inject)是如何工作的。我的问题是我有依赖于服务 B 的服务 A,但是当我将服务 A 注入(inject)我的测试服务 B 时,服务 B 变得未定
我正在为我的项目使用 android 应用程序启动、刀柄和空间。我在尝试排队工作时遇到错误: com.test E/WM-WorkerFactory: Could not instantiate co
我不确定这是什么糖语法,但让我向您展示问题所在。 def factors num (1..num).select {|n| num % n == 0} end def mutual_factors
简单的问题,我已经看过这个了:Managing imports in Scalaz7 ,但我不知道如何最小化注入(inject) right和 left方法到我的对象中以构造 \/ 的实例. 我确实尝
在我的 Aurelia SPA 中,我有一些我想在不同模块中使用的功能。它依赖于调用时给出的参数和单例的参数。有没有办法创建一个导出函数,我可以将我的 Auth 单例注入(inject)其中,而不必在
我是一名优秀的程序员,十分优秀!