您的位置:首页 > 其它

Quartz源码分析(二)

2015-08-14 19:07 351 查看
原文地址: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的实现和执行很简单, 主要是业务逻辑,以下简单的把类之间的关系整理下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: