ABP 依赖注入(2)

  • 依赖注入的使用
    • 构造方法注入
    • 属性注入
    • 从IServiceProvider解析服务
  • Autofac的使用
    • 容器替换
    • 拦截器与动态代理

接上一篇哈,链接ABP 依赖注入(1)

依赖注入的使用

构造方法注入

这是将服务注入类的最常用方法,是将依赖项注入类的首选方式,也是微软推崇的模式。这样,除非提供了所有构造方法注入的依赖项,否则无法构造类,显示的声明了类必需的服务,使开发人员一目了然。

public class BookAppService : ApplicationService
{private readonly IBookRepository _bookRepository;public TaxAppService(IBookRepository bookRepository){_bookRepository = bookRepository;}public void DoSomething(){//...使用 _bookRepository...}
}

属性注入

Microsoft依赖注入库不支持属性注入, 属性注入是Abp框架使用autofac容器替换了微软默认的容器之后才能使用的,属于autofac的特性。

public class BookAppService : ITransientDependency
{public ILogger<BookAppService> Logger { get; set; }public BookAppService(){Logger = NullLogger<BookAppService>.Instance;}public void DoSomething(){//...使用 Logger 写日志...}
}

属性注入依赖项通常被视为可选依赖项.这意味着不是必须的,没有它们服务也可以正常工作.Logger就是这样的依赖项,BookAppService可以继续工作而无需日志记录。为了使依赖项成为可选的,我们通常会为依赖项设置默认值。一般是接口的一个空实现,内部不做任何操作。

属性注入的一个限制是你不能在构造函数中使用依赖项,因为它是在对象构造之后设置的.

从IServiceProvider解析服务

public class MyService : ITransientDependency
{private readonly IServiceProvider _serviceProvider;public MyService(IServiceProvider serviceProvider){_serviceProvider = serviceProvider;}public void DoSomething(){using (var scope = _serviceProvider.CreateScope()){var service1 = scope.ServiceProvider.GetService<IMyService1>();// …}}
}

通过GetServiceGetRequiredService可以直接从容器中解析出我们需要的服务,这两个方法有一定的区别,推荐使用GetRequiredService方法。

这种情况下一般会使用using (var scope = _serviceProvider.CreateScope()){}创建一个域,以便解析出来的服务能够安全的被释放,这也能够减少一些内存消耗。

要注意的一个点是,在以前的ASP.NET Boilerplate 中服务的手动解析使用是通过IocManager的,这是静态类,通过IocManager.Instance可以获得容器对象,很方便使用。但是在现在的ABP中已经将这种方式移除了,以至于有时候在静态类中需要使用一些服务的时候很不方便(虽然这种方式不是很正确,但是确实有时候会有这样子的需求)。

所以在项目中如果真的有需要的话,可以自己构建一个类似于IocManager的方式,但是不推荐这样子用,因为在某些情况确实会存在一些问题,导致一些资源和生命周期的冲突,特别是在单元测试之中。

/// <summary>
/// ServiceManager构建一个单例,用于寄放IServiceProvider
/// 使用此类时,需要在应用启动的时候,调用Init方法
/// 一般情况下不推荐使用
/// </summary>
public class ServiceManager
{private ServiceManager(){}public static IServiceProvider ServiceProvider { get; private set; }public static void Init(IServiceProvider service){ServiceProvider = service;}
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{var app = context.GetApplicationBuilder();// 保存全局Iocif (app != null){ServiceManager.Init(app.ApplicationServices);}
}

Autofac的使用

容器替换

Abp框架中使用autofac依赖注入框架替换了微软默认的容器,在volo.abp.autofac模块中按照模块化设计的思想进行了稍微的封装,提供了便捷的替换方式。

使用autofac替换默认容器的方式:

(1) 在startup类中的ConfigureServices()中,在添加Abp的依赖注入时,通过选项替换。

public IServiceProvider ConfigureServices(IServiceCollection services)
{services.AddApplication<MyWebModule>(options =>{//Integrate Autofac!options.UseAutofac();});return services.BuildServiceProviderFromFactory();
}

(2) 在program.cs中,在.net Core 主机(host)创建的时候,调用userAutofac()扩展方法。

internal static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();}).UseAutofac();

拦截器与动态代理

Abp框架使用autofac替换微软默认容器的目的,主要就是为了利用autofac的拦截器功能,这是一种动态aop的实现方式,可以动态的拦截往容器中注册的类,做一些想要的操作。abp框架中的很多横切关注点都是通过这种方式实现的,如权限认证,审计等。

在模块类的PreConfigureServices()中,可以使用OnRegistred()方法,注册一个回调,每次有类向容器中注册时,都会调用这个回调。在回调中,我们可以对当前注册的类型进行判断(一般通过接口、特性等),如果满足我们的条件,就添加一个拦截器。




在我们调用useAutofac()时,内部会调用UseServiceProviderFactory()创建了一个AbpAutofacServiceProviderFactory,这是实现了微软IServiceProviderFactory<>接口的一个容器工厂,任何容器提供了这个接口实现类,并且按照约定提供了ContainerBuilder,都可以作为.net core中的依赖注入容器。

在.net Core应用程序启动的时候会调用IServiceProviderFactory<>接口的CreateBuilder(IServiceCollection services)方法,我们注册的回调函数就是在这个时候执行的。遍历每一个类,在多个回调中进行执行,符合条件的都会添加一个拦截器。



最终是向autofac容器注册拦截器。

拦截器类需要实现IAbpInterceptor接口,或者继承AbpInterceptor,实现其中的InterceptAsync方法。如果对某一个类配置了拦截器,实际上它在注册到容器中时,abp会基于拦截器动态生成一个代理类,再将代理类注册到autofac中。

动态代理是基于Castle实现的。abp继承了Castle动态代理的AsyncDeterminationInterceptor,通过继承了AsyncInterceptorBase使用适配器模式将拦截器进行包装,并且将方法执行的参数进行封装传递到我们定义的拦截器中。



执行被拦截的类的方法时,实际上通过代理类在执行InterceptAsync()方法,这类似于传统过滤器的效果,所以通过这种方式,我们可以在方法执行前后添加一些和业务无关的全局的操作,即一些横切关注点。

关于Abp依赖注入这一块的内容,整理了三天的时间,写着写着发现挺多的了,整理完发现已经快一点了,希望对百度看到这篇文章的人有帮助。

有点晚,洗澡休息了,晚安!

ABP 依赖注入(2)相关推荐

  1. 基于DDD的.NET开发框架 - ABP依赖注入

    返回ABP系列 ABP是"ASP.NET Boilerplate Project (ASP.NET样板项目)"的简称. ASP.NET Boilerplate是一个用最佳实践和流行 ...

  2. ABP 依赖注入(1)

    ABP 依赖注入(1) Abp依赖注入的配置方式 手动注册依赖注入关系 按照约定自动注册 通过特性注册 泛型类的注册 依赖注入实现了系统之间.模块之间和对象之间依赖关系的解耦,基本上是现代应用程序框架 ...

  3. abp项目怎样发布到服务器,ABP框架的基础配置及依赖注入讲解

    配置ABP 配置是通过在自己模块的PreInitialize方法中来实现的 代码示例如下: ? 和orchard类似,abp框架一开始就被设计成模块化的,不同的模块可以通过abp框架来进行配置.举个例 ...

  4. ABP 详解系列4:ABP框架的基础配置及依赖注入讲解

    ABP框架的基础配置及依赖注入讲解 这篇文章主要介绍了ABP框架的基础配置及依赖注入讲解,是ABP框架上手使用的基本,要的朋友可以参考下 配置ABP 配置是通过在自己模块的PreInitialize方 ...

  5. 使用 Autofac 进行依赖注入

    先说下为什么翻译这篇文章,既定的方向是架构,然后为了学习架构就去学习一些架构模式.设计思想. 突然有一天发现依赖注入这种技能.为了使得架构可测试.易维护.可扩展,需要架构设计为松耦合类型,简单的说也就 ...

  6. ABP理论学习之依赖注入

    返回总目录 本篇目录 什么是依赖注入 传统方式产生的问题 解决办法 依赖注入框架 ABP中的依赖注入基础设施 注册 解析 其他 ASP.NET MVC和ASP.NET Web API集成 最后提示 什 ...

  7. [Abp vNext 源码分析] - 3. 依赖注入与拦截器

    一.简要说明 ABP vNext 框架在使用依赖注入服务的时候,是直接使用的微软提供的 Microsoft.Extensions.DependencyInjection 包.这里与原来的 ABP 框架 ...

  8. 【转】ABP源码分析六:依赖注入的实现

    ABP的依赖注入的实现有一个本质两个途径:1.本质上是依赖于Castle这个老牌依赖注入的框架.2.一种实现途径是通过实现IConventionalDependencyRegistrar的实例定义注入 ...

  9. ABP VNext系列(二)-详解ABP的依赖注入

    ABP VNext系列(二)-详解ABP的依赖注入 上一篇 : ABP VNext系列(一)-第一个ABP VNext 目录 ABP VNext系列(二)-详解ABP的依赖注入 一.什么是依赖注入 1 ...

最新文章

  1. 通过BeanShell获取UUID并将参数传递给Jmeter
  2. 五分钟带你了解哈希算法
  3. 前端不为人知的一面--前端冷知识集锦
  4. java中的private public protected
  5. BlueCat 批量网站查询工具,全网最快的查询工具!!
  6. jQuery: 选择器(DOM,name,属性,元素)
  7. OpenGL vscode 安装与配置
  8. Word插入脚注不显示编号
  9. 深入解析淘宝Diamond之客户端架构
  10. 企业网络:安全只能靠两招
  11. java 实现限流器,可用于Rest接口请求处理 | Java工具类
  12. [计算机网络] --- RSTP运行原理及配置
  13. Robot Framework作者建议如何选择自动化测试框架
  14. 项目管理(四):项目整合管理
  15. 餐厅无线AP覆盖具有哪些特点
  16. Linux Network- Muti_thread and Multi_process TCP server
  17. 学java三年年薪_Java码农如何只奋斗3年就能达到年薪100万成为顶级架构师?
  18. silabs GPIO的配置与应用
  19. vue打包文件过大、Vue打包压缩
  20. OWASP Top 10十大风险 – 10个最重大的Web应用风险与攻防

热门文章

  1. 网络营销与广告的密切关系
  2. 视频转码:如何批量一键给视频进行转码?
  3. 浏览器扩展程序插件兼容谷歌、360浏览器
  4. 深度学习8.池化的概念
  5. ffmpeg 硬压字幕的实现
  6. HDU2060 Snooker斯诺克
  7. Python实验二:分析1996~2015年人口数据特征间的关系、分析并绘制鸢尾花数据的散点图和箱线图
  8. html中显示优酷视频,html5 - h5页面上如何播放优酷视频
  9. c语言c 哪个好,c语言与c++有什么区别 哪个更好学
  10. MYSQL通过索引进行优化