當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
Spring Boot定时任务-Job类对象注入
生活随笔
收集整理的這篇文章主要介紹了
Spring Boot定时任务-Job类对象注入
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
如何在我們的任務類當中,去完成其他對象的注入,Job類中注入對象,回到我們的代碼當中,這個是我們編寫的Job類,比如我們在Job類當中呢,我要使用到我業務下某個類的某個方法,那我們是不是要將我們業務層的對象注入到這當中,那我們怎么去注入呢,首先我們來編寫一個業務代碼,現在我就直接編寫一個業務類了@Service
public class UsersService {public void addUsers(){System.out.println("Add Users......");}
}然后在這里加一個@Service,在這里加一個方法addUsers,在這里我們去打印呢一句話,然后在我們的QuartzDemo5下,那我們就用一下@Autowired,這樣我們就完成了一個注入public class QuartzDemo2 implements Job {@Autowiredprivate UsersService usersService;@Overridepublic void execute(JobExecutionContext arg0) throws JobExecutionException {System.out.println("Execute...."+new Date());this.usersService.addUsers();}
}然后在這個方法里我再加一句話,通過usersService去調用它的addUsers方法,比較簡單,那我們加完以后,看能不能將我們的UserService注入進來,我們找到啟動類,去運行,觀察一下控制臺,這個時候就有異常出現了,而且報的是空指針異常,是哪一行報的呢,是這一行this.usersService.addUsers();這一行報空指針,說明什么,我們這個userService沒有注入進來,那么我們分析一下,他為什么沒有將UserService注入進來呢,我們還得看一下QuartzConfig這個類,我提供了一個方法,這個方法能夠返回JobDetailFactoryBean,然后我創建了一個JobDetailFactoryBean,并且我在這個對象下,去調用一個setJobClass,把我們的QuartzDemo2的class,也就是這個對象的實例化完全交給JobDetailFactoryBean他來處理了,那么他是怎么實例化的呢,我們可以看一下源碼,其實JobDetailFactoryBean在實例QuartzDemo2對象的時候,實例化我們的任務類的時候,他用的是org.springframework.scheduling.quartz.AdaptableJobFactory這個類下的一個方法,叫createJobInstance/*** Create an instance of the specified job class.* <p>Can be overridden to post-process the job instance.* @param bundle the TriggerFiredBundle from which the JobDetail* and other info relating to the trigger firing can be obtained* @return the job instance* @throws Exception if job instantiation failed*/
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {return bundle.getJobDetail().getJobClass().newInstance();
}我們看一下這個方法,其實這個方法比較簡單,在這里就是把我們的類拿到,然后調了一個newInstance,這是什么意思呢,他對我們傳過來類的實例化方式,采用的就是反射的機制來實例化,那么他用反射,就意味著我們現在這個對象的實例化,并沒有經過Spring的處理,如果沒有被Spring實例化,那么就意味著在Spring的IOC容器當中,就沒有QuartzDemo2這個對象,沒有這個對象,那他肯定是無法完成注入,因為Spring的注入是要求注入的對象和被注入的對象,都必須在Spring的IOC容器里存在,這樣才能完成對象的注入,這是他的一個要求,所以說現在呢,我們可以看到,正因為他并不是Sping去實例化的,這個這個過程,而是通過JobDetailFactoryBean,他這里的一個方法來完成實例化的,是通過反射的,所以這個對象是無法注入的,那么這個問題已經找到了,接下來我們看怎么解決,其實對于這個問題的解決方案,我們可以采用這樣的一種方式去做,我編寫一個類,然后我也去繼承AdaptableJobFactory,然后在這個繼承的過程當中,我去重寫createJobInstance方法,重寫的目的是什么呢,你現在把這個對象創建完,先別返回,先別著急返回,我在這個方法當中呢,先將你創建的對象,手動的添加到IOC的容器當中,并且去完成注入,這樣是不是就可以把QuartzDemo里面userService就給注入進來了,這是我們解決問題的一個方式,我們來看怎么去實現,在這里我們需要去繼承這個類,我們寫一個class,就叫MyAdaptableJobFactory@Component("myAdaptableJobFactory")
public class MyAdaptableJobFactory extends AdaptableJobFactory {//AutowireCapableBeanFactory 可以將一個對象添加到SpringIOC容器中,并且完成該對象注入@Autowiredprivate AutowireCapableBeanFactory autowireCapableBeanFactory;/*** 該方法需要將實例化的任務對象手動的添加到springIOC容器中并且完成對象的注入*/@Overrideprotected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {Object obj = super.createJobInstance(bundle);//將obj對象添加Spring IOC容器中,并完成注入this.autowireCapableBeanFactory.autowireBean(obj);return obj;}}然后讓他去繼承AdaptableJobFactory,然后我在這里去重寫createJobInstance方法,然后你這個方法該去創建還是去創建,只是創建完了別返回,他創建完了會返回一個Object對象,現在創建完這個對象以后,我在返回之前,是不是要將他加入到Spring的IOC容器中,并且完成注入,這里先把方法說明一下,該方法需要將實例化的任務對象,手動的添加到SpringIOC容器中,并且完成對象的注入,那么我們怎么把他放到SpringIOC的容器里,并且完成注入呢,這個時候我們需要依賴于另一個對象,所以在這里我先去注入一個對象,這個對象是誰呢,他的名字叫AutowireCapableBeanFactory,需要這樣的一個對象,在這里我們來解釋一下這個對象的作用,其實這個對象的作用呢,就是將我們的對象,可以將一個對象添加到SpringIOC的容器中,并且完成該對象的注入,也就是說你通過這個對象,把一個bean對象,它會把它放到Spring的IOC容器當中,所有需要注入的過程,做一個注入處理,那我們在這里就用到這個對象了,將obj對象=添加到Spring IOC容器中,并完成注入,那怎么去做呢,我們需要調用它的一個方法,這個方法叫什么呢,叫autowireBean,在這里我們把誰放到里面呢,把obj放到里面,就會把userService完成注入的操作,這樣我們一個類就寫好了,你這個類要想真正的能用,你是不是要把它實例化出來,那靠誰實例化呢,這肯定還得依賴于Spring,所以我們在這里加一個@Component,加一個這個注解,然后在這里可以給對象起一個id,這個大家應該懂什么意思,那么這個類寫完了我們怎么去用呢,產生異常的原因我們不寫了,因為我們分析完了,然后編寫一個類,編寫一個MyAdaptableJobFactory,解決該問題,這樣就可以解決了嗎,很顯然還是不允許,還得多一個步驟,回到我們的QuartzConfig當中,我們注意SchedulerFactoryBean對象,這個是完成Trigger的一個設置,那其實這個對象除了可以設置一個Trigger以外,他還可以重新設置AdaptableJobFactory,允許你新的設置AdaptableJobFactory,怎么去設置呢@Bean
public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean,MyAdaptableJobFactory myAdaptableJobFactory){SchedulerFactoryBean factory = new SchedulerFactoryBean();//關聯triggerfactory.setTriggers(cronTriggerFactoryBean.getObject());factory.setJobFactory(myAdaptableJobFactory);return factory;
}在這個對象下他有一個方法,叫setJobFactory,允許你重新設置一個job工廠,那其實我們現在要做的事,通過Spring創建的myAdaptableJobFactory拿過來,交給他,讓他去調用createJobInstance,并且將對象放到IOC容器當中,同時完成注入,那么怎么去交給他呢,需要注入,再這個方法當中再去注入一個參數,MyAdaptableJobFactory myAdaptableJobFactory,這個參數的名稱叫什么呢,就可以用我們定義的字符串myAdaptableJobFactory,就把這個對象交到SchedulerFactoryBean當中,他就可以去調用我們的createJobInstance,完成對象的實例化,這是最后一步,修改QuartzConfig類,關鍵的一點就是,關鍵就是能夠返回SchedulerFactoryBean,我們再添加一個參數,關鍵是MyAdaptableJobFactory他的一個定義,然后就是setJobFactory方法,把這個對象set進去,接下來我們來測試一下,我們這種解決問題的方式能不能解決問題,我們啟動main方法,啟動類去run一下,我們可以看到控制臺輸出的結果是沒有問題的,我們的定時任務方法執行了,同時addUser執行了,addUser不就是userService里面的東西嗎,所以這種方式是可以解決這個問題的,可能大家覺得這種方式可能會比較繁瑣,倒不是那么很繁瑣,要明白他的含義,我們做個總結吧,最關鍵的一點就是,在給你實例化Job對象的時候,我們的QuartzDemo2,在實例化對象的時候,并沒有通過Spring,沒有通過Spring完成IOC的注入,那么我們解決問題的方式呢,重寫回到我們的這個類的時候,調的一個方法,這個方法位于org.springframework.scheduling.quartz.AdaptableJobFactory然后重寫它的createJobInstance方法,最關鍵的一點就是,我們把它所實例化的一個對象,拿過來,通過我們使用的一個叫AutowireCapableBeanFactory,來手動的把它加入到IOC容器當中,并且完成一個屬性的注入,屬性注入就是UsersService的一個注入,然后我們要將類實例化出來怎么辦呢,上面加一個注解@Component("myAdaptableJobFactory"),實例化出來之后怎么去用呢,回到我們的QuartzConfig當中,在返回SchedulerFactoryBean的方法當中,加一個參數,把我們的參數加到里面,一個方法的的注入,在這里通過SchedulerFactoryBean對象,調用setJobFactory,把我們新的創建對象myAdaptableJobFactory,我們對象實例化的一個工廠,交給他,他來調用createJobInstance,完成對象的一個實例化,同時加入到SpringIOC并完成注入,這樣我們的QuartzDemo2的usersService就有值了,這是他解決問題的一個流程
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.learn</groupId><artifactId>spring-boot-quartz</artifactId><version>0.0.1-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.12.RELEASE</version></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><!-- springBoot的啟動器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 添加Scheduled坐標 --><!-- <dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency> --><!-- Quartz坐標 --><!-- <dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.1</version></dependency> --><!-- Quartz坐標 --><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.1</version><exclusions><exclusion><artifactId>slf4j-api</artifactId><groupId>org.slf4j</groupId></exclusion></exclusions></dependency><!-- 添加Scheduled坐標 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><!-- Sprng tx 坐標 --><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId></dependency></dependencies>
</project>
package com.learn.config;import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;@Component("myAdaptableJobFactory")
public class MyAdaptableJobFactory extends AdaptableJobFactory {//AutowireCapableBeanFactory 可以將一個對象添加到SpringIOC容器中,并且完成該對象注入@Autowiredprivate AutowireCapableBeanFactory autowireCapableBeanFactory;/*** 該方法需要將實例化的任務對象手動的添加到springIOC容器中并且完成對象的注入*/@Overrideprotected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {Object obj = super.createJobInstance(bundle);//將obj對象添加Spring IOC容器中,并完成注入this.autowireCapableBeanFactory.autowireBean(obj);return obj;}}
package com.learn.quartz;import java.util.Date;import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;import com.learn.service.UsersService;/*** Job類*/
public class QuartzDemo2 implements Job {@Autowiredprivate UsersService usersService;@Overridepublic void execute(JobExecutionContext arg0) throws JobExecutionException {System.out.println("Execute...."+new Date());this.usersService.addUsers();}
}
package com.learn.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;import com.learn.quartz.QuartzDemo2;/*** Quartz配置類* @author Leon.Sun**/
@Configuration
public class QuartzConfig {/*** 1.創建Job對象*/@Beanpublic JobDetailFactoryBean jobDetailFactoryBean(){JobDetailFactoryBean factory = new JobDetailFactoryBean();//關聯我們自己的Job類factory.setJobClass(QuartzDemo2.class);return factory;}/*** 2.創建Trigger對象* 簡單的Trigger*/
// @Bean
// public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
// SimpleTriggerFactoryBean factory = new SimpleTriggerFactoryBean();
// //關聯JobDetail對象
// factory.setJobDetail(jobDetailFactoryBean.getObject());
// //該參數表示一個執行的毫秒數
// factory.setRepeatInterval(2000);
// //重復次數
// factory.setRepeatCount(5);
// return factory;
// }/*** Cron Trigger*/@Beanpublic CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){CronTriggerFactoryBean factory = new CronTriggerFactoryBean();factory.setJobDetail(jobDetailFactoryBean.getObject());//設置觸發時間factory.setCronExpression("0/2 * * * * ?");return factory;}// @Bean
// public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean){
// SchedulerFactoryBean factory = new SchedulerFactoryBean();
// //關聯trigger
// factory.setTriggers(simpleTriggerFactoryBean.getObject());
//
// return factory;
// }/*** 3.創建Scheduler對象*/@Beanpublic SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean,MyAdaptableJobFactory myAdaptableJobFactory){SchedulerFactoryBean factory = new SchedulerFactoryBean();//關聯triggerfactory.setTriggers(cronTriggerFactoryBean.getObject());factory.setJobFactory(myAdaptableJobFactory);return factory;}
}
package com.learn;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;/*** *spring Boot 整合Quartz案例**/
@SpringBootApplication
@EnableScheduling
public class QuartzApp {public static void main(String[] args) {SpringApplication.run(QuartzApp.class, args);}
}
package com.learn.service;import org.springframework.stereotype.Service;@Service
public class UsersService {public void addUsers(){System.out.println("Add Users......");}
}
?
總結
以上是生活随笔為你收集整理的Spring Boot定时任务-Job类对象注入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Boot定时任务-Spri
- 下一篇: SpringCloud与dubbo的区别