温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java中怎么实现即时Quartz Job注入Bean

发布时间:2021-11-18 10:06:25 来源:亿速云 阅读:487 作者:iii 栏目:编程语言

这篇文章主要讲解了“java中怎么实现即时Quartz Job注入Bean”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java中怎么实现即时Quartz Job注入Bean”吧!

现今Spring已经成为企业级应用开发的事实框架,由于即时Quartz Job一般情况下不是Spring Bean,此时Job中就需要想办法获取Bean。

即时Job区别于周期/定时Job,是根据业务需要随时提交的Quartz Job,常见于界面提交后台的耗时任务(例如:导入/导出)。

接下来先简单看一下几种获取Spring Bean的方式:

第一种:定义AppCtxUtils工具类,用于获取Bean。

@Component
public class AppCtxUtils implements ApplicationContextAware {

  private static ApplicationContext appCtx;

  @Override
  public void setApplicationContext(ApplicationContext appCtx) throws BeansException {
    this.appCtx = appCtx;
  }

  public static ApplicationContext getAppCtx() {
    return appCtx;
  }

  public static <T> T getBean(Class<T> clazz) {
    return appCtx.getBean(clazz);
  }
  
  public static <T> T getBean(String beanName) {
    return (T) appCtx.getBean(beanName);
  }
}
public class AppCtxUtilsExampleJob implements Job {

  private ExampleService exampleService = AppCtxUtils.getBean(ExampleService.class);
  // 此处省略...

  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    // 此处省略...
  }
}

点评:这是一种使用最广泛的一种方式。

第二种:通过JobDataMap参数的方式传递ApplicationContext或Bean。

public class JobDataMapExampleJob implements Job {
  // 定义KEY
  public static final String KEY_APP_CTX = "appCtx";

  // 此处省略...
  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    // 从JobDataMap中取出ApplicationContext
    ApplicationContext appCtx = (ApplicationContext) getJobDataMap(context).get(KEY_APP_CTX);
    // 通过ApplicationContext取各种Bean
    ExampleService exampleService = appCtx.getBean(ExampleService.class);
    // 此处省略...
  }

  private JobDataMap getJobDataMap(JobExecutionContext context) {
    return context.getJobDetail().getJobDataMap();
  }
}

第三种:JobDetail配置为prototype Bean。

  • 定义Job,使用注解注入Bean。

// 定义成Bean
@Component("prototypeJobDetailExampleJob")
public class PrototypeJobDetailExampleJob implements Job {
  // 采用注解注入
  @Autowired
  private ExampleService exampleService;

  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    // 此处省略...
  }
}
  • 配置prototype JobDetail Bean。

<bean scope="prototype" id="prototypeJobDetailExampleJob.jobDetail"
  class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  <!-- 此处确保名称不重复 -->
  <property name="name" value="#{PrototypeJobDetailExampleJob.getNewUuid()}" />
  <property name="group" value="groupName" />
  <property name="targetObject" ref="prototypeJobDetailExampleJob"/>
  <property name="targetMethod" value="execute" />
</bean>
  • 立即调度

// 从Spring ApplicationContext中获取JobDetail。
JobDetail jobDetail = AppCtxUtils.getBean("prototypeJobDetailExampleJob.jobDetail");

// 此处省略代码

scheduler.addJob(jobDetail, false);
String myTrigger = UUID.randomUUID().toString();
Trigger trigger = TriggerBuilder.newTrigger() //
    .withIdentity(myTrigger, "groupName") //
    .forJob(jobDetail) //
    .startNow() //
    .build();
scheduler.scheduleJob(trigger);

点评:PrototypeJobDetailExampleJob以Spring Bean方式编写很简洁,但是配置和使用较复杂。

第四种:Spring提供对Quartz的支持的一种方式。

  • 定义Job

public class SchedulerContextExampleJob implements Job {
  // 定义KEY
  public static final String KEY_APP_CTX = "appCtx";

  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    try {
      ApplicationContext appCtx = getApplicationContext(context);
      // 通过ApplicationContext取各种Bean
      ExampleService exampleService = appCtx.getBean(ExampleService.class);

      // 此处代码省略
    } catch (Exception e) {
      throw new JobExecutionException(e);
    }
  }

  private ApplicationContext getApplicationContext(JobExecutionContext context)
      throws SchedulerException {
    // 从SchedulerContext中取出ApplicationContext
    return (ApplicationContext) context.getScheduler().getContext().get(KEY_APP_CTX);
  }
}
  • 配置JobDetail及Scheduler

<bean id="scheduler"
  class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  <!--  -->
  <property name="applicationContextSchedulerContextKey" value="appCtx"/>
  <!-- 省略其他配置 -->
</bean>

以上四种写法要么写法冗长,要么配置复杂。对有强迫症的程序员够优雅,那么接下来介绍一种更优雅的方式。

优雅的写法

public class ExampleJob implements Job {
  @Autowired
  private ExampleService exampleService;

  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    // 此处省略...
  }
}

ExampleJob与第三种PrototypeJobDetailExampleJob的最大区别:ExampleJob非Spring Bean,但依然可以使用Spring注解进行Bean的注入。

那如何实现呢?

基本原理:将Quartz实例化的JOB对象实例在使用前让Spring容器帮忙注入。

废话不多说直接上代码。

  • 扩展SpringBeanJobFactory。

public class SpringAutowireCapableJobFactory extends SpringBeanJobFactory
    implements ApplicationContextAware {
  private ApplicationContext applicationContext;

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }

  @Override
  protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
    Object jobInstance = super.createJobInstance(bundle);
    // 此处用Spring处理对象
    applicationContext.getAutowireCapableBeanFactory().autowireBean(jobInstance);
    return jobInstance;
  }

}
  • 配置scheduler时指定jobFactory为SpringAutowireCapableJobFactory

<bean id="scheduler"
  class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  <property name="jobFactory">
    <bean
      class="example.SpringAutowireCapableJobFactory" />
  </property>
  <!-- 省略其他... -->
</bean>

感谢各位的阅读,以上就是“java中怎么实现即时Quartz Job注入Bean”的内容了,经过本文的学习后,相信大家对java中怎么实现即时Quartz Job注入Bean这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI