石英、Unity 和。网

发布于 2024-12-04 02:51:14 字数 503 浏览 1 评论 0原文

是否可以注册一个quartz作业来始终使用由Unity DI容器注入的相同的IJob实例?我有一个来自 Unity DI 的类 Monitor 的单个实例“监视器”,我将其注册为:

container.RegisterType<IMonitor, Monitor>(new ContainerControlledLifetimeManager())

并且我的 IJob 实现期望将该监视器实例注入其中:

class MyJob : IJob {
...
[Dependency] IMonitor monitor {get; set;}
...
void Execute()
...
}

但是当quartz 事件触发时,会在注入依赖项之前调用 IJob.Execute() 实现。我应该如何让它发挥作用?我应该考虑其他 DI 容器或调度程序吗?

谢谢

Is it possible to register a quartz job to always use the same IJob instance injected by DI container Unity? I have a single instance "monitor" of a class Monitor coming from Unity DI, wich I registered as:

container.RegisterType<IMonitor, Monitor>(new ContainerControlledLifetimeManager())

and my IJob implementation expects to have that monitor instance injected into it:

class MyJob : IJob {
...
[Dependency] IMonitor monitor {get; set;}
...
void Execute()
...
}

but when quartz events fire, the IJob.Execute() implementation is called before the dependency gets injected. How should I get this working? Should I consider other DI containers or Schedulers instead ?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

多情癖 2024-12-11 02:51:14

Quartz 将在每次火灾事件时重新实例化作业接口实现。如果您想保留状态,建议使用IStatefulJob作业执行之间:

IStatefulJob 实例遵循与常规规则略有不同的规则
IJob 实例。关键区别在于它们关联的 JobDataMap
每次执行作业后都会重新保留,从而保留
下一次执行的状态。另一个区别是有状态的
作业不允许同时执行,这意味着新的触发器
在 IJob.Execute 方法完成之前发生的事件将是
延迟。

来自 Quartz 教程

有状态作业

现在,关于作业状态数据(又名 JobDataMap)的一些附加说明:
作业实例可以定义为“有状态”或“无状态”。
无状态作业仅在其执行时存储其 JobDataMap
被添加到调度程序中。这意味着对
作业执行期间作业数据映射的内容将会丢失,
并且下次执行作业时不会看到它。你有
可能猜到了,有状态作业正好相反 - 它的 JobDataMap
每次执行作业后都会重新存储。其副作用之一是
使作业有状态的原因是它不能同时执行。或者
换句话说:如果作业是有状态的,并且触发器尝试“触发”
当作业已经执行时,触发器将阻塞(等待)
直到上一次执行完成。

通过让 Job 实现 StatefulJob 来将其“标记”为有状态
接口,而不是 Job 接口。

您的另一个选择是实现您自己的 JobFactory:

作业“实例”

关于这个主题的最后一点现在可能很明显,也可能不明显:
您可以创建一个作业类,并存储许多“实例”
通过创建多个实例在调度程序中对其进行定义
JobDetails - 每个都有自己的一组属性和 JobDataMap -
并将它们全部添加到调度程序中。

当触发器触发时,与其关联的作业将通过以下方式实例化
Scheduler 上配置的 JobFactory。默认的JobFactory
只需在作业类上调用 newInstance() 即可。 您可能想要创建
您自己实现 JobFactory 来完成以下任务
让应用程序的 IoC 或 DI 容器生成/初始化
作业实例

Quartz will reinstantiate job interface implementation on every fire event. It is recommended to use IStatefulJob if you want to preserve state between job executions:

IStatefulJob instances follow slightly different rules from regular
IJob instances. The key difference is that their associated JobDataMap
is re-persisted after every execution of the job
, thus preserving
state for the next execution. The other difference is that stateful
jobs are not allowed to Execute concurrently, which means new triggers
that occur before the completion of the IJob.Execute method will be
delayed.

From Quartz tutorial:

StatefulJob

Now, some additional notes about a job's state data (aka JobDataMap):
A Job instance can be defined as "stateful" or "non-stateful".
Non-stateful jobs only have their JobDataMap stored at the time they
are added to the scheduler. This means that any changes made to the
contents of the job data map during execution of the job will be lost,
and will not seen by the job the next time it executes. You have
probably guessed, a stateful job is just the opposite - its JobDataMap
is re-stored after every execution of the job. One side-effect of
making a job stateful is that it cannot be executed concurrently. Or
in other words: if a job is stateful, and a trigger attempts to 'fire'
the job while it is already executing, the trigger will block (wait)
until the previous execution completes.

You 'mark' a Job as stateful by having it implement the StatefulJob
interface, rather than the Job interface.

Another option for you is to implement your own JobFactory:

Job 'Instances'

One final point on this topic that may or may not be obvious by now:
You can create a single job class, and store many 'instance
definitions' of it within the scheduler by creating multiple instances
of JobDetails - each with its own set of properties and JobDataMap -
and adding them all to the scheduler.

When a trigger fires, the Job it is associated to is instantiated via
the JobFactory configured on the Scheduler. The default JobFactory
simply calls newInstance() on the job class. You may want to create
your own implementation of JobFactory to accomplish things such as
having your application's IoC or DI container produce/initialize the
job instance
.

去了角落 2024-12-11 02:51:14

看看 Quartz.Unity。

https://www.nuget.org/packages/Quartz.Unity/1.0.1

文档非常稀疏,但看起来您需要做的就是将 nuget 包和以下行添加到容器配置中。

var container = new UnityContainer().AddNewExtension<Quartz.Unity.QuartzUnityExtension>();

Have a look at Quartz.Unity.

https://www.nuget.org/packages/Quartz.Unity/1.0.1

Doc is very sparse, but it appears that all you need to do is add the nuget package and the following line to your container configuration.

var container = new UnityContainer().AddNewExtension<Quartz.Unity.QuartzUnityExtension>();
阳光下慵懒的猫 2024-12-11 02:51:14

您可以通过实现自己的 JobFactory 来做到这一点。您必须实现 IJobFactory 接口:

public interface IJobFactory
{
    /// <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>
    /// <p>
    /// It should be extremely rare for this method to throw an exception -
    /// basically only the 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 wih instantiating the Job. 
    /// </p>
    /// 
/// </remarks>
    /// <param name="bundle">
    /// The TriggerFiredBundle from which the <see cref="JobDetail" />
    /// and other info relating to the trigger firing can be obtained.
    /// </param>
    /// <throws>  SchedulerException if there is a problem instantiating the Job. </throws>
    /// <returns> the newly instantiated Job
    /// </returns>
    IJob NewJob(TriggerFiredBundle bundle);
}

然后,将调度程序的quartz.scheduler.jobFactory.type 属性设置为作业工厂的类型。

作为参考,这是quartz.net 使用的默认作业工厂:

public class SimpleJobFactory : IJobFactory
{
    private static readonly ILog Log = LogManager.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 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 wih instantiating the Job.
/// </remarks>
    /// <param name="bundle">The TriggerFiredBundle from which the <see cref="JobDetail" />
    /// and other info relating to the trigger firing can be obtained.</param>
    /// <returns>the newly instantiated Job</returns>
    /// <throws>  SchedulerException if there is a problem instantiating the Job. </throws>
    public virtual IJob NewJob(TriggerFiredBundle bundle)
    {
        JobDetail jobDetail = bundle.JobDetail;
        Type jobType = jobDetail.JobType;
        try
        {
            if (Log.IsDebugEnabled)
            {
                Log.Debug(string.Format(CultureInfo.InvariantCulture, "Producing instance of Job '{0}', class={1}", jobDetail.FullName, jobType.FullName));
            }

            return (IJob) ObjectUtils.InstantiateType(jobType);
        }
        catch (Exception e)
        {
            SchedulerException se = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Problem instantiating class '{0}'", jobDetail.JobType.FullName), e);
            throw se;
        }
    }
}

有趣的行是:

  return (IJob) ObjectUtils.InstantiateType(jobType);

You can do this by implementing your own JobFactory. You'll have to implement the IJobFactory interface:

public interface IJobFactory
{
    /// <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>
    /// <p>
    /// It should be extremely rare for this method to throw an exception -
    /// basically only the 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 wih instantiating the Job. 
    /// </p>
    /// 
/// </remarks>
    /// <param name="bundle">
    /// The TriggerFiredBundle from which the <see cref="JobDetail" />
    /// and other info relating to the trigger firing can be obtained.
    /// </param>
    /// <throws>  SchedulerException if there is a problem instantiating the Job. </throws>
    /// <returns> the newly instantiated Job
    /// </returns>
    IJob NewJob(TriggerFiredBundle bundle);
}

Then, set the scheduler's quartz.scheduler.jobFactory.type property to your job factory's type.

For reference, here's the default job factory that quartz.net uses:

public class SimpleJobFactory : IJobFactory
{
    private static readonly ILog Log = LogManager.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 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 wih instantiating the Job.
/// </remarks>
    /// <param name="bundle">The TriggerFiredBundle from which the <see cref="JobDetail" />
    /// and other info relating to the trigger firing can be obtained.</param>
    /// <returns>the newly instantiated Job</returns>
    /// <throws>  SchedulerException if there is a problem instantiating the Job. </throws>
    public virtual IJob NewJob(TriggerFiredBundle bundle)
    {
        JobDetail jobDetail = bundle.JobDetail;
        Type jobType = jobDetail.JobType;
        try
        {
            if (Log.IsDebugEnabled)
            {
                Log.Debug(string.Format(CultureInfo.InvariantCulture, "Producing instance of Job '{0}', class={1}", jobDetail.FullName, jobType.FullName));
            }

            return (IJob) ObjectUtils.InstantiateType(jobType);
        }
        catch (Exception e)
        {
            SchedulerException se = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Problem instantiating class '{0}'", jobDetail.JobType.FullName), e);
            throw se;
        }
    }
}

The interesting line is:

  return (IJob) ObjectUtils.InstantiateType(jobType);
︶ ̄淡然 2024-12-11 02:51:14

创建一个覆盖 SimpleJobFactory 的 CustomJobfactory 并使用 spring 实例化作业类。

/// <summary>
/// Custom Job Factory
/// </summary>
public class CustomJobFactory : SimpleJobFactory
{
    /// <summary>
    /// Application context
    /// </summary>
    private IApplicationContext context;

    /// <summary>
    /// Initializes a new instance of the <see cref="CustomJobFactory" /> class.
    /// </summary>
    public CustomJobFactory()
    {
        this.context = ContextRegistry.GetContext();
    }

    /// <summary>
    /// Creates a new job instance
    /// </summary>
    /// <param name="bundle">Trigger bundle</param>
    /// <param name="scheduler">Job scheduler</param>
    /// <returns></returns>
    public override IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        IJobDetail jobDetail = bundle.JobDetail;
        Type jobType = jobDetail.JobType;
        return this.context.GetObject(jobType.Name) as IJob;
    }

    /// <summary>
    /// Return job
    /// </summary>
    /// <param name="job">Job instance</param>
    public override void ReturnJob(IJob job)
    {
    }
}

Create a CustomJobfactory that overrides SimpleJobFactory and use spring to instantiate the job classes.

/// <summary>
/// Custom Job Factory
/// </summary>
public class CustomJobFactory : SimpleJobFactory
{
    /// <summary>
    /// Application context
    /// </summary>
    private IApplicationContext context;

    /// <summary>
    /// Initializes a new instance of the <see cref="CustomJobFactory" /> class.
    /// </summary>
    public CustomJobFactory()
    {
        this.context = ContextRegistry.GetContext();
    }

    /// <summary>
    /// Creates a new job instance
    /// </summary>
    /// <param name="bundle">Trigger bundle</param>
    /// <param name="scheduler">Job scheduler</param>
    /// <returns></returns>
    public override IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        IJobDetail jobDetail = bundle.JobDetail;
        Type jobType = jobDetail.JobType;
        return this.context.GetObject(jobType.Name) as IJob;
    }

    /// <summary>
    /// Return job
    /// </summary>
    /// <param name="job">Job instance</param>
    public override void ReturnJob(IJob job)
    {
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文