原文位址:http://smurfs.iteye.com/blog/1157692
Quartz架構執行的任務需要寫在一個實作Job接口的類中,在實作類中的execute(JobExecutionContext context)中執行相關的操作,通過實作Job接口來使你的Java 元件可以很簡單的被scheduler執行,下面是job接口:
/**
* <p>
* Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code>
* fires that is associated with the <code>Job</code>.
* </p>
*
* <p>
* The implementation may wish to set a
* {@link JobExecutionContext#setResult(Object) result} object on the
* {@link JobExecutionContext} before this method exits. The result itself
* is meaningless to Quartz, but may be informative to
* <code>{@link JobListener}s</code> or
* <code>{@link TriggerListener}s</code> that are watching the job's
* execution.
* </p>
*
* @throws JobExecutionException
* if there is an exception while executing the job.
*/
void execute(JobExecutionContext context)
throws JobExecutionException;
如上,你會看到job觸發器出發時,job的execute方法會被執行。那麼,scheduler的job是通過何種方式建立和執行的呢。先來看看job的部署,job是通過jobdetail scheduler到架構中去的,然後通過getJobClass()方法擷取到job實作類的class位元組碼的,通過jobFactory的newJob()方法反射出Java 的具體執行個體,然後在JobRunShell線程對象的run方法中執行。
1、 先看看jobdetail的建立,在quartz2.2.1中,jobdetail是通過jobbuilder建立
/**
* Produce the <code>JobDetail</code> instance defined by this
* <code>JobBuilder</code>.
*
* @return the defined JobDetail.
*/
public JobDetail build() {
JobDetailImpl job = new JobDetailImpl();
job.setJobClass(jobClass);
job.setDescription(description);
if(key == null)
key = new JobKey(Key.createUniqueName(null), null);
job.setKey(key);
job.setDurability(durability);
job.setRequestsRecovery(shouldRecover);
if(!jobDataMap.isEmpty())
job.setJobDataMap(jobDataMap);
return job;
}
Jobbuilder 通過靜态方法 newjob() 不同重載來建立 Jobbuilder ,通過 withIdentity() 重載設定參數,如下:
/**
* Create a JobBuilder with which to define a <code>JobDetail</code>,
* and set the class name of the <code>Job</code> to be executed.
*
* @return a new JobBuilder
*/
public static JobBuilder newJob(Class <? extends Job> jobClass) {
JobBuilder b = new JobBuilder();
b.ofType(jobClass);
return b;
}
/**
* Use a <code>JobKey</code> with the given name and default group to
* identify the JobDetail.
*
* <p>If none of the 'withIdentity' methods are set on the JobBuilder,
* then a random, unique JobKey will be generated.</p>
*
* @param name the name element for the Job's JobKey
* @return the updated JobBuilder
* @see JobKey
* @see JobDetail#getKey()
*/
public JobBuilder withIdentity(String name) {
key = new JobKey(name, null);
return this;
}
2、 建立好jobdetail後,scheduler通過線程類JobRunShell來執行Job。
通過initialize方法中調用JobFactory的newJob()建立Job執行個體。
public void initialize(QuartzScheduler sched)
throws SchedulerException {
this.qs = sched;
Job job = null;
JobDetail jobDetail = firedTriggerBundle.getJobDetail();
try {
job = sched.getJobFactory().newJob(firedTriggerBundle, scheduler);
} catch (SchedulerException se) {
sched.notifySchedulerListenersError(
"An error occured instantiating job to be executed. job= '"
+ jobDetail.getKey() + "'", se);
throw se;
} catch (Throwable ncdfe) { // such as NoClassDefFoundError
SchedulerException se = new SchedulerException(
"Problem instantiating class '"
+ jobDetail.getJobClass().getName() + "' - ", ncdfe);
sched.notifySchedulerListenersError(
"An error occured instantiating job to be executed. job= '"
+ jobDetail.getKey() + "'", se);
throw se;
}
this.jec = new JobExecutionContextImpl(scheduler, firedTriggerBundle, job);
}
JobFactory 的 newJob() 方法通過反射使用預設無參數的構造方法實作 job 執行個體建立,如下:
public Job newJob(TriggerFiredBundle bundle, Scheduler Scheduler) throws SchedulerException {
JobDetail jobDetail = bundle.getJobDetail();
Class<? extends Job> jobClass = jobDetail.getJobClass();
try {
if(log.isDebugEnabled()) {
log.debug(
"Producing instance of Job '" + jobDetail.getKey() +
"', class=" + jobClass.getName());
}
return jobClass.newInstance();
} catch (Exception e) {
SchedulerException se = new SchedulerException(
"Problem instantiating class '"
+ jobDetail.getJobClass().getName() + "'", e);
throw se;
}
}
Job 的執行很簡單,直接調用 execute 方法即可:
public QuartzScheduler(QuartzSchedulerResources resources, long idleWaitTime, @Deprecated long dbRetryInterval)
throws SchedulerException {
this.resources = resources;
if (resources.getJobStore() instanceof JobListener) {
addInternalJobListener((JobListener)resources.getJobStore());
}
this.schedThread = new QuartzSchedulerThread(this, resources);
ThreadExecutor schedThreadExecutor = resources.getThreadExecutor();
schedThreadExecutor.execute(this.schedThread);
if (idleWaitTime > 0) {
this.schedThread.setIdleWaitTime(idleWaitTime);
}
jobMgr = new ExecutingJobsManager();
addInternalJobListener(jobMgr);
errLogger = new ErrorLogger();
addInternalSchedulerListener(errLogger);
signaler = new SchedulerSignalerImpl(this, this.schedThread);
if(shouldRunUpdateCheck())
updateTimer = scheduleUpdateCheck();
else
updateTimer = null;
getLog().info("Quartz Scheduler v." + getVersion() + " created.");
}
Job 的實作和執行很簡單, 主要是業務邏輯,以下簡單的把類之間的關系整理下: