ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Quartz使用AutoFac依赖注入问题小结

2021-09-03 22:04:41  阅读:205  来源: 互联网

标签:AutoFac Quartz 自定义 接口 IExceptionJobHandler Job QuartzAutofacFactoryModule 小结 注入



theme: channing-cyan
highlight: a11y-dark

背景

最近在做一个需求,就是在Job中捕捉异常,然后通过邮件或者消息的方式推送给指定人员,在需求实现的过程中遇到的一个注入问题,觉得很有意思,特此记录。

如果您看了觉得或者已经有更好的办法,烦请告诉我一下,我们可以共同讨论,如果有地方不对,也请不吝斧正.


遇到的问题

由于不同功能的Job很多,每一个Job中都要实现对发生异常的消息发送,现有的Job是这样的

image.png

为了实现这个需求,也为了以后更好的维护,我准备用事件委托的模式去实现,将对异常消息发送的业务逻辑拆出,保证职责单一,思路如下:

  1. 在Job和IJob中间再加一层IExceptionJobHandler接口作为约束.
  2. 接口中定义一个发送异常消息的事件PushException.
  3. 然后每一个Job在异常时去触发这个事件,外部只需要统一订阅一个事件即可.

image.png

到目前这一步是可行的可能有人会问为什么要用接口,而不用父类,因为接口的关系没有父类紧密,用接口后续其他地方要用,可以稍加修改就好了 虽然不是很完美的设计,但是还是比较清晰的,但是另外一个问题来了,我如何通过Autofac注入这个Job呢,原来直接继承自Ijob现在加了一层.


问题分析

这个问题花了我整整大约4个小时的时间去找解决方案,研究依赖注入的方式并且在网上搜了好久,但没什么进展,然后重新梳理了一下框架依赖注入的代码,发现是走错路了,注入Job使用的是Autofac.Extras.Quartz来完成的,这下知道方向了.

在WebAPI中使用Quartz需要在AppStart中加入以下代码:

 var builder = new ContainerBuilder();
 builder.RegisterModule(new QuartzAutofacFactoryModule
 {
     ConfigurationProvider = c => schedulerConfig
 });

这个QuartzAutofacFactoryModule里面一定有我想知道的东西,就在Github上下载了Autofac.Extras.Quartz的源码,打开一看,果然发现了它的真面目.

image.png

这里面就是对Job依赖注入的,但是没有发现对Job的注册和构建,注意箭头标记的,它有一个AutofacJobFactory类,接收一个ILifetimeScope,而它的作用就是用来构建Job为作用域周期生效的服务实例.

image.png


解决方案

  1. 上面分析出构建Job服务实例的是一个叫AutofacJobFactory的工厂,那么我们应该由他入手,找到构建服务的代码,我们看到

    • 在调用ResolveJobInstance方法时返回一个IJob,我要思考的问题是如何把我自定义的接口IExceptionJobHandler注入进去,让我们Job实例拥有这个接口中定义事件呢?
  2. 根据上述设计IExceptionJobHandler继承自IJob,那也就是说这里直接可以把Ijob换成IExceptionJobHandler,该如何实现呢?

  3. 我们观察到在AutofacJobFactory构建服务的方法是一个 虚方法 ,所以可以利用 继承 来解决,我们新建一个ExtendAutofacJobFactory来重写它将Ijob换成IExceptionJobHandler

public class ExtendAutofacJobFactory : AutofacJobFactory
  {
     protected override IJob ResolveJobInstance(ILifetimeScope nestedScope, IJobDetail jobDetail)
       {
            //验证Job是否派生自IExceptionJobHandler
            if (typeof(IExceptionJobHandler).IsAssignableFrom(jobDetail.JobType))
            {
                IExceptionJobHandler instance = null;
                instance = (IExceptionJobHandler)CreateIJob(nestedScope, jobDetail);
                //注册事件统一处理入口
                instance.PushException += pushExceptionMessageManager.Value.ExceptionJobHandler
                    return instance;
            }
            else
            {
                return base.ResolveJobInstance(nestedScope, jobDetail);
            }

       }
  }
  1. 接下来我们需要把重写的构造工厂放入QuartzAutofacFactoryModule中,但是QuartzAutofacFactoryModule也没有提供设置自定义工厂的入口,那只有依然选择 继承 的方式去重写它.

  2. 然后修改QuartzAutofacFactoryModule加载服务时将服务构造工厂换成我们自己扩展的ExtendAutofacJobFactory.

image.png

  1. 在AppStart中Autofac注册服务地方将QuartzAutofacFactoryModule改为自定义的ExtendQuartzAutofacFactoryModule,至此完成了自定义注入.
builder.RegisterModule(new ExtendQuartzAutofacFactoryModule
{
    ConfigurationProvider = c => schedulerConfig
});

总结

在被人问到面向对象的特征时,99%的人都能回答出来:[封装] [继承] [多态],甚至会对提出问题的人在内心中深深的鄙视,这xx怎么问这种问题,但是经过一段时间开发经验的沉淀和积累之后,发现往往最简单、最基础的知识,才是最最重要的.

标签:AutoFac,Quartz,自定义,接口,IExceptionJobHandler,Job,QuartzAutofacFactoryModule,小结,注入
来源: https://www.cnblogs.com/yuxl01/p/15225056.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有