有關Quartz.NET,與一線碼農大佬對個線?

跟[一線碼農大佬]翻譯的某技術文對個線

最近看到一線碼農大佬翻譯的《如何在 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實例。

翻源碼:

//----------------選自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工廠類]動作的由來,  知其然更知其所以然,如有勘誤,歡迎留言賜教。

Reference: 

ASP.NET Core+Quartz.Net實現web定時任務 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章