瞭解了Quartz基本原理後,再回頭看公司的程序:java
BeanInvokingJobDetailFactoryBean 做爲自定義的實現,裏面有函數 afterPropertiesSet 調用了 spring
jobdetail, 而jobdetail 會使用內部類BeanInvokingJob, BeanInvokingJob剛是用了反射進行調用各個jobapache
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.Scheduler; import org.quartz.StatefulJob; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.util.MethodInvoker; public class BeanInvokingJobDetailFactoryBean implements FactoryBean, BeanNameAware, InitializingBean, ApplicationContextAware { protected static ApplicationContext applicationContext; private Log logger = LogFactory.getLog(getClass()); private String group = Scheduler.DEFAULT_GROUP; private boolean concurrent = true; private boolean durable = false; private boolean volatility = false; private boolean shouldRecover = false; private String[] jobListenerNames; private String beanName; private JobDetail jobDetail; private String targetBean; private String targetMethod; private Object[] arguments; // targetBean getter setter 省略 // targetMethod getter setter 省略 public Object getObject() throws Exception { return jobDetail; } public Class getObjectType() { return JobDetail.class; } public boolean isSingleton() { return true; } public void setBeanName(String beanName) { this.beanName = beanName; } public void afterPropertiesSet() throws Exception { try { logger.debug("start"); logger.debug("Creating JobDetail "+beanName); jobDetail = new JobDetail(); jobDetail.setName(beanName); jobDetail.setGroup(group); jobDetail.setJobClass(concurrent ? BeanInvokingJob.class : StatefulBeanInvokingJob.class); jobDetail.setDurability(durable); jobDetail.setVolatility(volatility); jobDetail.setRequestsRecovery(shouldRecover); jobDetail.getJobDataMap().put("targetBean", targetBean); jobDetail.getJobDataMap().put("targetMethod", targetMethod); jobDetail.getJobDataMap().put("arguments", arguments); logger.debug("Registering JobListener names with JobDetail object "+beanName); if (this.jobListenerNames != null) { for (int i = 0; i < this.jobListenerNames.length; i++) { this.jobDetail.addJobListener(this.jobListenerNames[i]); } } logger.info("Created JobDetail: "+jobDetail+"; targetBean: "+ targetBean+"; targetMethod: "+targetMethod+"; arguments: "+arguments+";"); } finally { logger.debug("end"); } } public void setConcurrent(boolean concurrent) { this.concurrent = concurrent; } public void setDurable(boolean durable) { this.durable = durable; } public void setGroup(String group) { this.group = group; } public void setJobListenerNames(String[] jobListenerNames) { this.jobListenerNames = jobListenerNames; } public void setShouldRecover(boolean shouldRecover) { this.shouldRecover = shouldRecover; } public void setVolatility(boolean volatility) { this.volatility = volatility; } public void setApplicationContext(ApplicationContext context) throws BeansException { applicationContext = context; } public void setArguments(Object[] arguments) { this.arguments = arguments; } public static class BeanInvokingJob implements Job { protected Log logger = LogFactory.getLog(getClass()); public void execute(JobExecutionContext context) throws JobExecutionException { try { logger.debug("start"); String targetBean = context.getMergedJobDataMap().getString("targetBean"); logger.debug("targetBean is "+targetBean); if(targetBean==null) throw new JobExecutionException("targetBean cannot be null.", false); String targetMethod = context.getMergedJobDataMap().getString("targetMethod"); logger.debug("targetMethod is "+targetMethod); if(targetMethod==null) throw new JobExecutionException("targetMethod cannot be null.", false); Object argumentsObject = context.getMergedJobDataMap().get("arguments"); Object[] arguments = (argumentsObject instanceof String) ? null : (Object[])argumentsObject; logger.debug("arguments array is "+arguments); Object bean = applicationContext.getBean(targetBean); logger.debug("applicationContext resolved bean name/id '"+targetBean+"' to "+bean); MethodInvoker beanMethod = new MethodInvoker(); beanMethod.setTargetObject(bean); beanMethod.setTargetMethod(targetMethod); beanMethod.setArguments(arguments); beanMethod.prepare(); logger.info("Invoking Bean: "+targetBean+"; Method: "+ targetMethod+"; arguments: "+arguments+";"); beanMethod.invoke(); } catch(JobExecutionException e) { throw e; } catch(Exception e) { throw new JobExecutionException(e); } finally { logger.debug("end"); } } } public static class StatefulBeanInvokingJob extends BeanInvokingJob implements StatefulJob { // No additional functionality; just needs to implement StatefulJob. } }