将属性注入 QuartzJobObject

发布于 2024-12-06 16:52:41 字数 758 浏览 1 评论 0原文

我是否正确地认为我的 QuartzJobObject 不能注入任何 DAO 或其他 Spring 管理的对象?

希望我可以做这样的事情(orderService 是我想要注入的):

<object name="checkPendingOrdersJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
  <property name="JobType" value="Munch.ScheduledTasks.CheckPendingOrdersJob" />
  <!-- We can inject values through JobDataMap -->
  <property name="JobDataAsMap">
    <dictionary>
      <!--entry key="UserName" value="Alexandre" /-->
    </dictionary>      
  </property>
  <property name="orderService" ref="orderService"/>
</object>

...我知道由于它的类型而没有意义。但是,我可以通过某种方式注入一些 DAO、服务等。但我无法弄清楚。我该怎么做?

Am I right in thinking that my QuartzJobObject can't have any DAO's or other Spring-managed objects injected into it?

Was hoping I could do something like this (orderService is what I want to inject):

<object name="checkPendingOrdersJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
  <property name="JobType" value="Munch.ScheduledTasks.CheckPendingOrdersJob" />
  <!-- We can inject values through JobDataMap -->
  <property name="JobDataAsMap">
    <dictionary>
      <!--entry key="UserName" value="Alexandre" /-->
    </dictionary>      
  </property>
  <property name="orderService" ref="orderService"/>
</object>

...which I know doesn't make sense because of the type it is. But, I could do with being able to inject some DAO's, Services etc somehow. I can't figure it out though. How can I do this?

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

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

发布评论

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

评论(2

无风消散 2024-12-13 16:52:41

这就是我最终得到的结果,它工作得很好(希望对其他人有用)

了解 Spring 上下文的作业工厂

/// <summary>
/// A custom job factory that is aware of the spring context
/// </summary>
public class ContextAwareJobFactory : AdaptableJobFactory, IApplicationContextAware
{
    /// <summary>
    /// The spring app context
    /// </summary>
    private IApplicationContext m_Context;

    /// <summary>
    /// Set the context
    /// </summary>
    public IApplicationContext ApplicationContext
    {
        set
        {
            m_Context = value;
        }
    }

    /// <summary>
    /// Overrides the default version and sets the context
    /// </summary>
    /// <param name="bundle"></param>
    /// <returns></returns>
    protected override object CreateJobInstance(TriggerFiredBundle bundle)
    {
        return m_Context.GetObject(bundle.JobDetail.JobType.Name, bundle.JobDetail.JobType);
    }
}

作业本身(检查数据库中的情况)记录,如果至少有 HomeManyMenuItemsIsOK 个,则一切都很好)。注意:menuService 是一个注入的 spring 管理对象,它本身有几个 DAO)。 HowManyMenuItemsIsOK 是通过作业数据映射传入的静态属性。

public class CheckMenuIsHealthyJob : QuartzJobObject 
{
    private static readonly ILog log = LogManager.GetLogger(typeof(CheckMenuIsHealthyJob));

    public IMenuService menuService { get; set; }
    public int HowManyMenuItemsIsOK { get; set; }

    /// <summary>
    /// Check how healthy the menu is by seeing how many menu items are stored in the database. If there
    /// are more than 'HowManyMenuItemsIsOK' then we're ok.
    /// </summary>
    /// <param name="context"></param>
    protected override void ExecuteInternal(JobExecutionContext context)
    {
        IList<MenuItem> items = menuService.GetAllMenuItems();
        if (items != null && items.Count >= HowManyMenuItemsIsOK)
        {
            log.Debug("There are " + items.Count + " menu items. Menu is healthy!");
        }
        else
        {
            log.Warn("Menu needs some menu items adding!");
        }

    }
}

最后是 Spring 配置

<!-- Scheduled Services using Quartz -->
  <!-- This section contains Quartz config that can be reused by all our Scheduled Tasks ---->  
  <!-- The Quartz scheduler factory -->
  <object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
    <!-- Tell Quartz to use our custom (context-aware) job factory -->
    <property name="JobFactory" ref="contextAwareJobFactory"/>

    <!-- Register the triggers -->
    <property name="triggers">
      <list>
        <ref object="frequentTrigger" />
      </list>
    </property>
  </object>  

  <!-- Funky new context-aware job factory -->
  <object name="contextAwareJobFactory" type="Munch.Service.ScheduledTasks.ContextAwareJobFactory" />

  <!-- A trigger that fires every 10 seconds (can be reused by any jobs that want to fire every 10 seconds) -->
  <object id="frequentTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz" lazy-init="true">
    <property name="jobDetail" ref="checkMenuIsHealthyJobDetail" />
    <property name="cronExpressionString" value="0/10 * * * * ?" />
  </object>  

  <!-- Now the job-specific stuff (two object definitions per job; 1) the job and 2) the job detail) --> 
  <!-- Configuration for the 'check menu is healthy job' -->
  <!-- 1) The job -->
  <object name="checkMenuIsHealthyJob" type="Munch.Service.ScheduledTasks.CheckMenuIsHealthyJob" singleton="false">
    <property name="menuService" ref="menuService"/>
  </object>

  <!-- 2) The job detail -->
  <object name="checkMenuIsHealthyJobDetail" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
    <property name="JobType" value="Munch.Service.ScheduledTasks.CheckMenuIsHealthyJob"/>
    <property name="JobDataAsMap">
      <dictionary>
        <entry key="HowManyMenuItemsIsOK" value="20" />
      </dictionary>
    </property>    
  </object>

This is what I've ended up with and it works perfectly (hopefully useful to someone else)

Job factory that is aware of Spring's context

/// <summary>
/// A custom job factory that is aware of the spring context
/// </summary>
public class ContextAwareJobFactory : AdaptableJobFactory, IApplicationContextAware
{
    /// <summary>
    /// The spring app context
    /// </summary>
    private IApplicationContext m_Context;

    /// <summary>
    /// Set the context
    /// </summary>
    public IApplicationContext ApplicationContext
    {
        set
        {
            m_Context = value;
        }
    }

    /// <summary>
    /// Overrides the default version and sets the context
    /// </summary>
    /// <param name="bundle"></param>
    /// <returns></returns>
    protected override object CreateJobInstance(TriggerFiredBundle bundle)
    {
        return m_Context.GetObject(bundle.JobDetail.JobType.Name, bundle.JobDetail.JobType);
    }
}

The job itself (checks the DB for records and if there are at least HomeManyMenuItemsIsOK of them, everything is good). Note: menuService is an injected spring-managed object that itself has several DAO's in it). HowManyMenuItemsIsOK is a static property that's passed in through the job data map.

public class CheckMenuIsHealthyJob : QuartzJobObject 
{
    private static readonly ILog log = LogManager.GetLogger(typeof(CheckMenuIsHealthyJob));

    public IMenuService menuService { get; set; }
    public int HowManyMenuItemsIsOK { get; set; }

    /// <summary>
    /// Check how healthy the menu is by seeing how many menu items are stored in the database. If there
    /// are more than 'HowManyMenuItemsIsOK' then we're ok.
    /// </summary>
    /// <param name="context"></param>
    protected override void ExecuteInternal(JobExecutionContext context)
    {
        IList<MenuItem> items = menuService.GetAllMenuItems();
        if (items != null && items.Count >= HowManyMenuItemsIsOK)
        {
            log.Debug("There are " + items.Count + " menu items. Menu is healthy!");
        }
        else
        {
            log.Warn("Menu needs some menu items adding!");
        }

    }
}

And finally the Spring config

<!-- Scheduled Services using Quartz -->
  <!-- This section contains Quartz config that can be reused by all our Scheduled Tasks ---->  
  <!-- The Quartz scheduler factory -->
  <object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
    <!-- Tell Quartz to use our custom (context-aware) job factory -->
    <property name="JobFactory" ref="contextAwareJobFactory"/>

    <!-- Register the triggers -->
    <property name="triggers">
      <list>
        <ref object="frequentTrigger" />
      </list>
    </property>
  </object>  

  <!-- Funky new context-aware job factory -->
  <object name="contextAwareJobFactory" type="Munch.Service.ScheduledTasks.ContextAwareJobFactory" />

  <!-- A trigger that fires every 10 seconds (can be reused by any jobs that want to fire every 10 seconds) -->
  <object id="frequentTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz" lazy-init="true">
    <property name="jobDetail" ref="checkMenuIsHealthyJobDetail" />
    <property name="cronExpressionString" value="0/10 * * * * ?" />
  </object>  

  <!-- Now the job-specific stuff (two object definitions per job; 1) the job and 2) the job detail) --> 
  <!-- Configuration for the 'check menu is healthy job' -->
  <!-- 1) The job -->
  <object name="checkMenuIsHealthyJob" type="Munch.Service.ScheduledTasks.CheckMenuIsHealthyJob" singleton="false">
    <property name="menuService" ref="menuService"/>
  </object>

  <!-- 2) The job detail -->
  <object name="checkMenuIsHealthyJobDetail" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
    <property name="JobType" value="Munch.Service.ScheduledTasks.CheckMenuIsHealthyJob"/>
    <property name="JobDataAsMap">
      <dictionary>
        <entry key="HowManyMenuItemsIsOK" value="20" />
      </dictionary>
    </property>    
  </object>
逆夏时光 2024-12-13 16:52:41

您可以通过覆盖 CreateJobInstance 来将属性/构造函数注入到您的作业中
AdaptableJobFactory 并注册新的 JobFactory 而不是默认的 JobFactory。

传入的 TriggerFiredBundle 为您提供了足够的信息来向上下文请求匹配的作业(基于约定)。 bundle.JobDetail.JobType.Namebundle.JobDetail.JobType 满足了我的需求,所以早在 2008 年我就得到了一些东西。像这样(该类是从 AdaptableJobFactory 派生的,并实现 IApplicationContextAware 来注入上下文):

public class ContextAwareJobFactory : AdaptableJobFactory, IApplicationContextAware
{
  private IApplicationContext m_Context;

  public IApplicationContext ApplicationContext
  {
    set
    {
      m_Context = value;
    }
  }

  protected override object CreateJobInstance( TriggerFiredBundle bundle )
  {
    return m_Context.GetObject( bundle.JobDetail.JobType.Name, bundle.JobDetail.JobType );
  }
}

您需要使用以下配置注册 ContextAwareJobFactory:

<objects xmlns="http://www.springframework.net">
  <!-- Some simple dependency -->
  <object name="SomeDependency" type="Namespace.SomeDependency, Assembly" />

  <!-- The scheduled job, gets the dependency. -->
  <object name="ExampleJob" type="Namespace.ExampleJob, Assembly" singleton="false">
    <constructor-arg name="dependency" ref="SomeDependency"/>
  </object>

  <!-- The JobDetail is configured as usual. -->
  <object name="ExampleJobDetail" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
    <property name="JobType" value="Namespace.ExampleJob, Assembly"/>        
  </object>

  <!-- The new JobFactory. -->
  <object name="ContextAwareJobFactory" type="Namespace.ContextAwareJobFactory, Assembly" />

  <!-- Set the new JobFactory onto the scheduler factory. -->
  <object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
    <property name="JobFactory" ref="ContextAwareJobFactory"/>
  </object>      
</objects>

我不知道是否有某事。 ootb 因为它是在 2008 年开发的,所以我没有关注quartz.net 的集成进度。

You can do property/constructor injection into your job by overiding CreateJobInstance of
AdaptableJobFactory and register your new JobFactory instead of the default one.

The passed in TriggerFiredBundle provides you with enough infos to ask the context for a matching job (based on conventions). bundle.JobDetail.JobType.Name and bundle.JobDetail.JobType fitted my need, so back in 2008 I ended up with sth. like this (the class is derived form AdaptableJobFactory and implements IApplicationContextAware to get the context injected):

public class ContextAwareJobFactory : AdaptableJobFactory, IApplicationContextAware
{
  private IApplicationContext m_Context;

  public IApplicationContext ApplicationContext
  {
    set
    {
      m_Context = value;
    }
  }

  protected override object CreateJobInstance( TriggerFiredBundle bundle )
  {
    return m_Context.GetObject( bundle.JobDetail.JobType.Name, bundle.JobDetail.JobType );
  }
}

You need to register the ContextAwareJobFactory using the following config:

<objects xmlns="http://www.springframework.net">
  <!-- Some simple dependency -->
  <object name="SomeDependency" type="Namespace.SomeDependency, Assembly" />

  <!-- The scheduled job, gets the dependency. -->
  <object name="ExampleJob" type="Namespace.ExampleJob, Assembly" singleton="false">
    <constructor-arg name="dependency" ref="SomeDependency"/>
  </object>

  <!-- The JobDetail is configured as usual. -->
  <object name="ExampleJobDetail" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
    <property name="JobType" value="Namespace.ExampleJob, Assembly"/>        
  </object>

  <!-- The new JobFactory. -->
  <object name="ContextAwareJobFactory" type="Namespace.ContextAwareJobFactory, Assembly" />

  <!-- Set the new JobFactory onto the scheduler factory. -->
  <object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
    <property name="JobFactory" ref="ContextAwareJobFactory"/>
  </object>      
</objects>

I don't know if there is sth. ootb since this was developed in 2008 and I did not followed the integration progress made for quartz.net.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文