今天在调试quartz(基于内存实现的定时任务)代码时,发现无法@Autowired注入bean服务
业务场景
需要定时同步钉钉组织以及人员信息,每天凌晨等BI抽取完成后进行,预计每天凌晨5点。
发现问题
代码如下:
/**
* @author: create by AdoreFT
* @version: v1.0
* @keyWord: Time is not waiting for me, you forgot to take me away.
* @description: DingTalkOrgTask
* @Date: 1/14/21 4:20 PM
**/
@DisallowConcurrentExecution
public class DingTalkOrgTask extends QuartzJobBean {
private static final Logger logger = LoggerFactory.getLogger(DingTalkOrgTask.class);
@Autowired
private DingTalkGetUsrInfomationService usrInfomationService;
@Autowired
private DingTalkGetOrgService orgService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//耗时监控
StopWatch stopWatch = new StopWatch();
stopWatch.start();
try {
//组织同步
orgService.uploadOrgToDD();
//人员同步
usrInfomationService.uploadUserToDD();
} catch (Exception e) {
logger.info(String.format("组织以及人员同步失败:%s MS", stopWatch.getTime()));
}finally {
stopWatch.stop();
}
logger.info(String.format("组织人员同步耗时总时间:%s MS", stopWatch.getTime()));
}
}
就如上代码所示:在继承QuartzJobBean来实现业务时,@Autowired无法注入到服务上,导致null空指针
通过网上查询原来:Spring容器可以管理Bean,但是Quartz的job是自己管理的,如果在Job中注入Spring管理的Bean,需要先把Quartz的Job也让Spring管理起来。
管理Quartz job Bean
通过自定义JobFactory,通过spring的AutowireCapableBeanFactory进行注入。
- AutowireCapableBeanFactory
它的功能主要是为了装配applicationContext管理之外的Bean。
- 自定义
JobFactory
代码如下:
/**
* @author: create by AdoreFT
* @version: v1.0
* @keyWord: Time is not waiting for me, you forgot to take me away.
* @description: UhiJobFactory
* @Date: 1/21/21 4:30 PM
**/
@Component
public class UhiJobFactory extends SpringBeanJobFactory {
@Autowired
private AutowireCapableBeanFactory beanFactory;
/**
* 这里覆盖了super的createJobInstance方法,对其创建出来的类再进行autowire。
*/
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
beanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
注意:此方法要由Spring管理 添加:@Component注解。
在QuartzConfig中引入 UhiJobFactory
代码实现如下:
/**
* @author: create by AdoreFT
* @version: v1.0
* @keyWord: Time is not waiting for me, you forgot to take me away.
* @description: QuartzConfig
* @Date: 1/13/21 3:31 PM
**/
@Configuration
public class QuartzConfig {
@Value("${cron.org_key}")
private String cronOrg;
@Autowired
private UhiJobFactory uhiJobFactory;
@Bean
public JobDetailFactoryBean jobOrgDetailFactoryBean(){
JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
jobDetailFactoryBean.setJobClass(DingTalkOrgTask.class);
return jobDetailFactoryBean;
}
/**
* 使用触发器
* cron(每天凌晨2点跑一次)
* */
@Bean
public CronTriggerFactoryBean cronOrgTriggerFactoryBean() {
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setJobDetail(jobOrgDetailFactoryBean().getObject());
cronTriggerFactoryBean.setCronExpression(cronOrg);
return cronTriggerFactoryBean;
}
@Bean
public SchedulerFactoryBean schedulerOrgFactoryBean(){
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setTriggers(cronOrgTriggerFactoryBean().getObject());
schedulerFactoryBean.setJobFactory(uhiJobFactory);
return schedulerFactoryBean;
}
@Bean(name="Scheduler")
public Scheduler schedulerOrg() {
return schedulerOrgFactoryBean().getScheduler();
}
}
如上代码:只需要在 schedulerFactoryBean.setJobFactory(uhiJobFactory);就可以。
SpringMVC 方式 需要在触发器中配置该JobFactory
<property name="jobFactory">
<bean class="com.uhi.applyment4sub.factory.UhiJobFactory" />
</property>







网友评论