前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >有关Quartz.NET,与一线码农大佬对个线?

有关Quartz.NET,与一线码农大佬对个线?

作者头像
有态度的马甲
发布2020-12-18 11:32:32
6510
发布2020-12-18 11:32:32
举报
文章被收录于专栏:精益码农精益码农
跟[一线码农大佬]翻译的某技术文对个线

最近看到一线码农大佬翻译的《如何在 ASP.NET Core 中使用 Quartz.NET 执行任务调度》, 行文思路:

  1. 安装Quartz.NET
  2. Quartz.NET 中的Job,triggers 和 Schedulers
  3. 创建 Scheduler
  4. 开启和停止 scheduler
  5. 创建 job 工厂
  6. 创建 JobMetadata 存储你的 job 元数据

不可否认,一线大佬的翻译文还是相当精准的, 但个人认为这篇文章的底稿有点硬输出,并没有以一个流畅、直观的编码思路来讲述[如何在ASP.NET Core中使用Quartz.NET 执行定时任务]。

尤其是下面这段:

想起我之前也写了《ASP.NET Core+Quartz.Net实现web定时任务》, 文章以一个简单的定时任务讲述了Quartz.NET在ASP.NET Core中的应用思路,遇河架桥,遇山开路。

这里我要解释一下上图中:为什么要自定义一个Job工厂?

先看下官方JobFactory的作用:

大意是说:

如果某触发器被触发,该触发器关联的Job将被调度器上配置的JobFactory初始化;

Quartz.NET默认的SimpleJobFactory工厂类,是利用反射+无参构造函数构造出Job实例。

翻源码:

代码语言:javascript
复制
//----------------选自Quartz.Simpl.SimpleJobFactory类-------------
using System;
using Quartz.Logging;
using Quartz.Spi;
using Quartz.Util;
namespace Quartz.Simpl
{
    /// <summary> 
    /// The default JobFactory used by Quartz - simply calls 
    /// <see cref="ObjectUtils.InstantiateType{T}" /> on the job class.
    /// </summary>
    /// <seealso cref="IJobFactory" />
    /// <seealso cref="PropertySettingJobFactory" />
    /// <author>James House</author>
    /// <author>Marko Lahma (.NET)</author>
    public class SimpleJobFactory : IJobFactory
    {
        private static readonly ILog log = LogProvider.GetLogger(typeof (SimpleJobFactory));

        /// <summary>
        /// Called by the scheduler at the time of the trigger firing, in order to
        /// produce a <see cref="IJob" /> instance on which to call Execute.
        /// </summary>
        /// <remarks>
        /// It should be extremely rare for this method to throw an exception -
        /// basically only the case where there is no way at all to instantiate
        /// and prepare the Job for execution.  When the exception is thrown, the
        /// Scheduler will move all triggers associated with the Job into the
        /// <see cref="TriggerState.Error" /> state, which will require human
        /// intervention (e.g. an application restart after fixing whatever
        /// configuration problem led to the issue with instantiating the Job).
        /// </remarks>
        /// <param name="bundle">The TriggerFiredBundle from which the <see cref="IJobDetail" />
        ///   and other info relating to the trigger firing can be obtained.</param>
        /// <param name="scheduler"></param>
        /// <returns>the newly instantiated Job</returns>
        /// <throws>  SchedulerException if there is a problem instantiating the Job. </throws>
        public virtual IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            IJobDetail jobDetail = bundle.JobDetail;
            Type jobType = jobDetail.JobType;
            try
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug($"Producing instance of Job '{jobDetail.Key}', class={jobType.FullName}");
                }

                return ObjectUtils.InstantiateType<IJob>(jobType);
            }
            catch (Exception e)
            {
                SchedulerException se = new SchedulerException($"Problem instantiating class '{jobDetail.JobType.FullName}'", e);
                throw se;
            }
        }

        /// <summary>
        /// Allows the job factory to destroy/cleanup the job if needed. 
        /// No-op when using SimpleJobFactory.
        /// </summary>
        public virtual void ReturnJob(IJob job)
        {
            var disposable = job as IDisposable;
            disposable?.Dispose();
        }
    }
}

//------------------节选自Quartz.Util.ObjectUtils类-------------------------
 public static T InstantiateType<T>(Type type)
{
     if (type == null)
     {
          throw new ArgumentNullException(nameof(type), "Cannot instantiate null");
     }
     ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
     if (ci == null)
     {
          throw new ArgumentException("Cannot instantiate type which has no empty constructor", type.Name);
     }
     return (T) ci.Invoke(new object[0]);
}

但是很多情况下我们定义的Job很可能依赖第三方服务,就比如一线大佬文中NotificationJob依赖了ILogger<NotificationJob> 服务。

这样默认的SimpleJobFactory不能满足实例化要求, 考虑将Job任务作为依赖注入组件,加入依赖注入容器。

关键思路:

IScheduler 开放了JobFactory 属性,便于你应用自定义的Job工厂; 在自定义Job工厂中,使用ASP.NET Core依赖注入容器IServiceProvider解析出特定的Job。

JobFactories may be of use to those wishing to have their application produce IJob instances via some special mechanism, such as to give the opportunity for dependency injection

这才有一线码农大佬原文 [创建Job工厂类]动作的由来, 知其然更知其所以然,如有勘误,欢迎留言赐教。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 精益码农 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档