ABP - 依赖注入(2)
这是将服务注入类的最常用方法,是将依赖项注入类的首选方式,也是微软推崇的模式。这样,除非提供了所有构造方法注入的依赖项,否则无法构造类,显示的声明了类必需的服务,使开发人员一目了然。
(资料图片仅供参考)
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 Logger { get; set; }public BookAppService(){ Logger = NullLogger.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();// …}}} 通过GetService、GetRequiredService可以直接从容器中解析出我们需要的服务,这两个方法有一定的区别,推荐使用GetRequiredService方法。
这种情况下一般会使用using (var scope = _serviceProvider.CreateScope()){} 创建一个域,以便解析出来的服务能够安全的被释放,这也能够减少一些内存消耗。
要注意的一个点是,在以前的ASP.NET Boilerplate 中服务的手动解析使用是通过IocManager的,这是静态类,通过IocManager.Instance可以获得容器对象,很方便使用。但是在现在的ABP中已经将这种方式移除了,以至于有时候在静态类中需要使用一些服务的时候很不方便(虽然这种方式不是很正确,但是确实有时候会有这样子的需求)。
所以在项目中如果真的有需要的话,可以自己构建一个类似于IocManager的方式,但是不推荐这样子用,因为在某些情况确实会存在一些问题,导致一些资源和生命周期的冲突,特别是在单元测试之中。
/// /// ServiceManager构建一个单例,用于寄放IServiceProvider/// 使用此类时,需要在应用启动的时候,调用Init方法/// 一般情况下不推荐使用/// 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(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(); }) .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 系列总结上一篇:ABP - 依赖注入(1)
标签:
为您推荐
广告
- ABP - 依赖注入(2)
- 全球消息!特索涅夫鼓励大连人队友:路途还很长,我们必须保持斗志和团结
- 海关总署允许多国20家境外水产品企业恢复对华出口 天天滚动
- 环球今头条!五香蛋做法?
- 市场指导价52.18万元 奥迪S4 Avant正式上市-世界新资讯
- 港股异动 | 纷美包装(00468)涨超3% 拟采购设备及扩建生产设施以提高产能-世界动态
- 环球视讯!永贵电器5月30日盘中涨幅达5%
- 国际硕士项目学制多少年?
- 宣风站(关于宣风站介绍)
- 传统零售业重压之下谋转型
- 当前热门:水发燃气:融资净买入398.34万元,融资余额1.37亿元(05-29)
- 重点聚焦!46寸液晶拼接屏尺寸大小_46寸液晶拼接屏尺寸
- 世界速讯:湖南衡阳:快乐晨练 轻松迎考
- 香山股份:拟5.1亿元收购均胜群英12%股权
- 网王同人原创男主_网王同人之玄夜|当前看点
- 新动态:深圳:1-4月全市规模以上工业增加值同比增长2.1%
- 李廷钊_关于李廷钊的介绍-每日快讯
- 1000kva等于多少mw 1000kva等于多少kw
- 环球消息!打篮球崴脚后怎么处理_崴脚后怎么处理
- 有鼻炎怎么办快速缓解(如果你有鼻炎怎么办?教你8个小妙招治疗鼻炎)
- 1【天天新要闻】今日不知道是怎么回事,在百度、搜狗、雅虎、搜搜等网站上搜到的MP3或者WMA格式的音乐都无法播放,无法在线听,但是可以下载到电脑上听。点开页面后,我会一直准备着,不管是哪首歌。
- 2【全球热闻】四部门联合启动高校毕业生等青年就业创业政策宣传周活动
- 3天天速读:夏收在即,上百台收割机无法下高速?官方回应了
- 4【速看料】中国代购行业市场发展现状分析
- 5Apple 为 SignChat 申请商标以提供手语服务_焦点
- 6坠入地狱网盘_坠入地狱迅雷下载_世界资讯
- 7音乐剧《愚公移山》在京演出
- 8金华市外国语实验学校小升初招生电脑派位具体时间+地点-全球信息
- 9生态环境部:2022年全国生态环境质量改善
- 10曾年赚百万的美妆博主,收入大跳水
广告
- 和黄医药(00013)将于美国临床肿瘤学会(ASCO)2023年年会公布最新研究结果_环球即时看
- 世界要闻:人生三大境界诗词(人生三大境界)
- 今日快看!时尚征途中的十字路口:ZARA在中国市场的发展与抉择
- 阿里巴巴企业文化是什么-环球百事通
- 雨水何时“下班”?洛阳发布最新天气预报 观热点
- 到泰国旅游要多少钱 泰国旅游要带多少钱
- 环球微资讯!内舒拿和辅舒良哪个性价比更高高_内舒拿和辅舒良哪个副作用大
- 三星Galaxy S23:高品质、高颜值
- 红酒储藏方法和步骤?
- 天天观焦点:96岁抗美援朝老兵再圆“军装梦”
- 雄兵连三什么时候上线(雄兵连3什么时候出)
- 饭饭粥粥(饭饭粥粥全集在线阅读)
- 丛珊个人资料年轻照片 丛珊个人资料
- 2023中关村论坛|北京市门头沟区京西产业引导基金正式发布
- 宇宙的印记之平行宇宙·代理黄金圣斗士传奇
- 微软宣布Windows全球用户超10亿!Win11是史上最可靠操作系统
- “520”登记数锐减,年轻人不想结婚?
- dnf高级炉岩碳成功率高吗_dnf高级炉岩碳怎么得 有什么用
- 如何使用柑橘制作除臭剂 关注
- 焦点速讯:总台记者全过程体验C919首次商业载客飞行
