service注入为null_如何解决quartz调度时候,job中的service为null的问题?
在需要用到調(diào)度任務(wù)的時候,發(fā)現(xiàn)job中的通過依賴注入的service對象為null.如下:
@Component public class ExpiredOrderJob implements Job {@Autowiredprivate EmployeeService employeeService; //這里的service對象為null@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {……} }問題的原因:
出現(xiàn)這個問題的根本原因,還得從spring的IOC和AOP的基本原理開始講起。
在IOC中,是spring先把需要放置到IOC容器的對象放入,然后在通過IOC機制去請求獲得該對象的時候,然后調(diào)用出來IOC容器中準(zhǔn)備好的對象。具體在springboot中的表現(xiàn),如果你在一個類中增加了Component的注解,或者在一個Configure中增加了Bean的注解,IOC就會明白你想要把該對象放入到容器,然后在需要容器幫你實例化的地方加入Autoware,容器就會把該對象給注入。需要注意的地方是,容器只能對容器注入的對象內(nèi)部的屬性注入,如果你通過自己的代碼new了一個對象,這對象里面的Autoware的屬性是不起作用的。很好理解,因為你的對象不在容器的管理范圍,容器就無法去注入。
而在quartz的job對象,是通過直接傳入job類的class,由quartz框架去實例化的,而非通過spring框架去實例化的,自然就無法完成注解。
JobDetail jobDetail = JobBuilder.newJob(ExpiredOrderJob.class) //把job.class傳入了jobBuilder.withIdentity("expireOrder","group1").build();解決的思路:
在job中通過Autoware注解去實現(xiàn),是不太可能了。而JobDetail 可以通過jobDataMap的屬性來傳遞對象,我們可以在需要spring注入的地方,把我們要注入的對象放到j(luò)obDataMap中去,然后在job中取出來使用,來繞道完成注解。
版本1:
//在調(diào)用調(diào)度器的地方去實現(xiàn)注入 @Autowired private EmployeeService employeeService; private void scheduleSumJob(Scheduler scheduler) throws SchedulerException{JobDetail jobDetail = JobBuilder.newJob(SumJob.class).withIdentity("sumJob","group1").build();jobDetail.getJobDataMap().put("service",employeeService);CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/2 * * * * ?");CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1","group1").withSchedule(scheduleBuilder).build();scheduler.scheduleJob(jobDetail,cronTrigger);} //在job中去實現(xiàn)調(diào)用 public class SumJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException{EmployeeService employeeService = (EmployeeService)jobExecutionContext.getJobDetail().getJobDataMap().get("service");employeeService.freshAreaEmployeeNum();} }經(jīng)過測試,我們已經(jīng)能解決了在job中無法注入的問題。但是也有一些缺點,比如我們要再數(shù)據(jù)庫中保存很多的任務(wù),而每個任務(wù)所調(diào)用service都不一樣。我們就無法在我們的使用調(diào)度器的地方去實現(xiàn)找到需要注入的對象,然后放到j(luò)obDataMap中去。我們得一個更加通用的辦法:比如我們把spring的容器的context注入,然后job中需要什么注入對象,就直接從context中去獲得 ,這樣就實現(xiàn)了通用性:
版本2:
@Autowired private ServletContext servletContext; private void scheduleSumJob(Scheduler scheduler) throws SchedulerException{JobDetail jobDetail = JobBuilder.newJob(SumJob.class).withIdentity("sumJob","group1").build();jobDetail.getJobDataMap().put("context",servletContext);CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/2 * * * * ?");CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1","group1").withSchedule(scheduleBuilder).build();scheduler.scheduleJob(jobDetail,cronTrigger);}job中對應(yīng)的變化
public class SumJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException{ServletContext context = (ServletContext)jobExecutionContext.getJobDetail().getJobDataMap().get("context");WebApplicationContext cxt = (WebApplicationContext) context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);EmployeeService employeeService = cxt.getBean(EmployeeService.class);employeeService.freshAreaEmployeeNum();} }這樣做的好處就是把service的注入的獲得延遲了,可以在job中更加靈活的調(diào)用所需要的對象,而無需在啟用調(diào)度器的地方去思考,更加通用,降低了耦合。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的service注入为null_如何解决quartz调度时候,job中的service为null的问题?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 海尔win7怎么重装 如何重新安装海尔w
- 下一篇: u盘的分区怎么恢复出厂设置 U盘如何恢复
