JobDetailFactoryBean与MethodInvokingJobDetailFactoryBean源码分析

Spring与Quartz集成详解:[url]http://donald-draper.iteye.com/blog/2323591[/url]
Spring与Quarzt整合时,job的定义有两种方式,分别为JobDetailFactoryBean与MethodInvokingJobDetailFactoryBean,这两种方法有什么不同呢,我们通过源码来看一下:
第一种:
public class JobDetailFactoryBean
implements FactoryBean, BeanNameAware, ApplicationContextAware, InitializingBean
{
public JobDetailFactoryBean()
{
jobDataMap = new JobDataMap();
durability = false;
requestsRecovery = false;
}
public void setName(String name)
{
this.name = name;
}

public void setGroup(String group)
{
this.group = group;
}

public void setDescription(String description)
{
this.description = description;
}
//设置beanName
public void setBeanName(String beanName)
{
this.beanName = beanName;
}
//设置applicationContext
public void setApplicationContext(ApplicationContext applicationContext)
{
this.applicationContext = applicationContext;
}
//设置applicationContextJobDataKey
public void setApplicationContextJobDataKey(String applicationContextJobDataKey)
{
this.applicationContextJobDataKey = applicationContextJobDataKey;
}
public void afterPropertiesSet()
{
//设置默认的job,name和group
if(name == null)
name = beanName;
if(group == null)
group = "DEFAULT";
if(applicationContextJobDataKey != null)
{
if(applicationContext == null)
throw new IllegalStateException("JobDetailBean needs to be set up in an ApplicationContext to be able to handle an 'applicationContextJobDataKey'");
//配置jobDataMap
getJobDataMap().put(applicationContextJobDataKey, applicationContext);
}
Class jobDetailClass;
try
{
jobDetailClass = ClassUtils.forName("org.quartz.impl.JobDetailImpl", getClass().getClassLoader());
}
catch(ClassNotFoundException ex)
{
jobDetailClass = org/quartz/JobDetail;
}
BeanWrapper bw = new BeanWrapperImpl(jobDetailClass);

MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("name", name);
pvs.add("group", group);
pvs.add("jobClass", jobClass);
pvs.add("jobDataMap", jobDataMap);
pvs.add("durability", Boolean.valueOf(durability));
pvs.add("requestsRecovery", Boolean.valueOf(requestsRecovery));
pvs.add("description", description);
//设置属性
bw.setPropertyValues(pvs);
//或JobDetail实例
jobDetail = (JobDetail)bw.getWrappedInstance();
}
//设置属性值
public void setPropertyValue(String propertyName, Object value)
throws BeansException
{
BeanWrapperImpl nestedBw;
try
{
nestedBw = getBeanWrapperForPropertyPath(propertyName);
}
PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
nestedBw.setPropertyValue(tokens, new PropertyValue(propertyName, value));
}
//设置job类
public void setJobClass(Class jobClass)
{
this.jobClass = jobClass;
}
//返回的是jobDetail
public JobDetail getObject()
{
return jobDetail;
}

public Class getObjectType()
{
return org/quartz/JobDetail;
}

public boolean isSingleton()
{
return true;
}

public volatile Object getObject()
throws Exception
{
return getObject();
}
private String name;
private String group;
private Class jobClass;
private JobDataMap jobDataMap;
private boolean durability;//任务完成之后是否依然保留到数据库,默认false
private boolean requestsRecovery;
private String description;
private String beanName;
private ApplicationContext applicationContext;
private String applicationContextJobDataKey;
private JobDetail jobDetail;
}

//bean包装实现类
public class BeanWrapperImpl extends AbstractPropertyAccessor
implements BeanWrapper
{

public BeanWrapperImpl(Class clazz)
{
nestedPath = "";
autoGrowNestedPaths = false;
autoGrowCollectionLimit = 2147483647;
registerDefaultEditors();
//设置bean包装实现类实例
setWrappedInstance(BeanUtils.instantiateClass(clazz));
}
public void setWrappedInstance(Object object)
{
setWrappedInstance(object, "", null);
}
public void setWrappedInstance(Object object, String nestedPath, Object rootObject)
{
Assert.notNull(object, "Bean object must not be null");
this.object = object;
this.nestedPath = nestedPath == null ? "" : nestedPath;
this.rootObject = "".equals(this.nestedPath) ? object : rootObject;
nestedBeanWrappers = null;
typeConverterDelegate = new TypeConverterDelegate(this, object);
setIntrospectionClass(object.getClass());
}
protected void setIntrospectionClass(Class clazz)
{
if(cachedIntrospectionResults != null && !clazz.equals(cachedIntrospectionResults.getBeanClass()))
cachedIntrospectionResults = null;
}
//返回包装类实例
public final Object getWrappedInstance()
{
return object;
}
private static final Log logger = LogFactory.getLog(org/springframework/beans/BeanWrapperImpl);
private Object object;
private String nestedPath;
private Object rootObject;
private AccessControlContext acc;
private CachedIntrospectionResults cachedIntrospectionResults;
private Map nestedBeanWrappers;
private boolean autoGrowNestedPaths;
private int autoGrowCollectionLimit;


}

//AbstractPropertyAccessor
public abstract class AbstractPropertyAccessor extends TypeConverterSupport
implements ConfigurablePropertyAccessor
{
//设置bean所有属性
public void setPropertyValues(PropertyValues pvs)
throws BeansException
{
setPropertyValues(pvs, false, false);
}
//设置bean所有属性
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
throws BeansException
{
List propertyAccessExceptions = null;
List propertyValues = (pvs instanceof MutablePropertyValues) ? ((MutablePropertyValues)pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues());
Iterator iterator = propertyValues.iterator();
do
{
if(!iterator.hasNext())
break;
PropertyValue pv = (PropertyValue)iterator.next();
try
{
setPropertyValue(pv);
}

} while(true)
}
//设置bean单个属性
public void setPropertyValue(PropertyValue pv)
throws BeansException
{
setPropertyValue(pv.getName(), pv.getValue());
}
}

第二种:
public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethodInvoker
implements FactoryBean, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean
{
public static class StatefulMethodInvokingJob extends MethodInvokingJob
implements StatefulJob
{}

public static class MethodInvokingJob extends QuartzJobBean
{
public void setMethodInvoker(MethodInvoker methodInvoker)
{
this.methodInvoker = methodInvoker;
}
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException
{
try
{
ReflectionUtils.invokeMethod(MethodInvokingJobDetailFactoryBean.setResultMethod, context, new Object[] {
methodInvoker.invoke()
});
}
}
}
public MethodInvokingJobDetailFactoryBean()
{
group = "DEFAULT";
concurrent = true;
beanClassLoader = ClassUtils.getDefaultClassLoader();
}
public void afterPropertiesSet()
throws ClassNotFoundException, NoSuchMethodException
{
//初始化MethodInvoker
prepare();
String name = this.name == null ? beanName : this.name;
Class jobClass = concurrent ? org/springframework/scheduling/quartz/MethodInvokingJobDetailFactoryBean$MethodInvokingJob : org/springframework/scheduling/quartz/MethodInvokingJobDetailFactoryBean$StatefulMethodInvokingJob;
if(jobDetailImplClass != null)
{
jobDetail = (JobDetail)BeanUtils.instantiate(jobDetailImplClass);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(jobDetail);
bw.setPropertyValue("name", name);
bw.setPropertyValue("group", group);
bw.setPropertyValue("jobClass", jobClass);
bw.setPropertyValue("durability", Boolean.valueOf(true));
//设置jobDetails的jobDataMap
((JobDataMap)bw.getPropertyValue("jobDataMap")).put("methodInvoker", this);
} else
{
jobDetail = new JobDetail(name, group, jobClass);
jobDetail.setVolatility(true);
jobDetail.setDurability(true);
jobDetail.getJobDataMap().put("methodInvoker", this);
}
if(jobListenerNames != null)
{
String as[] = jobListenerNames;
int i = as.length;
for(int j = 0; j < i; j++)
{
String jobListenerName = as[j];
if(jobDetailImplClass != null)
throw new IllegalStateException("Non-global JobListeners not supported on Quartz 2 - manually register a Matcher against the Quartz ListenerManager instead");
//添加job监听器
jobDetail.addJobListener(jobListenerName);
}

}
postProcessJobDetail(jobDetail);
}

protected void postProcessJobDetail(JobDetail jobdetail)
{
}
//获取目标类型
public Class getTargetClass()
{
Class targetClass = super.getTargetClass();
if(targetClass == null && targetBeanName != null)
{
Assert.state(beanFactory != null, "BeanFactory must be set when using 'targetBeanName'");
targetClass = beanFactory.getType(targetBeanName);
}
return targetClass;
}
//获取目标实例
public Object getTargetObject()
{
Object targetObject = super.getTargetObject();
if(targetObject == null && targetBeanName != null)
{
Assert.state(beanFactory != null, "BeanFactory must be set when using 'targetBeanName'");
targetObject = beanFactory.getBean(targetBeanName);
}
return targetObject;
}
//返回jobDetail
public JobDetail getObject()
{
return jobDetail;
}

public Class getObjectType()
{
return jobDetail == null ? org/quartz/JobDetail : jobDetail.getClass();
}

public boolean isSingleton()
{
return true;
}
public volatile Object getObject()
throws Exception
{
return getObject();
}
private static Class jobDetailImplClass;
private static Method setResultMethod;
private String name;
private String group;
private boolean concurrent;
private String targetBeanName;
private String jobListenerNames[];
private String beanName;
private ClassLoader beanClassLoader;
private BeanFactory beanFactory;
private JobDetail jobDetail;

static
{
try
{
jobDetailImplClass = ClassUtils.forName("org.quartz.impl.JobDetailImpl", org/springframework/scheduling/quartz/MethodInvokingJobDetailFactoryBean.getClassLoader());
}
try
{
Class jobExecutionContextClass = ClassUtils.forName("org.quartz.JobExecutionContext", org/springframework/scheduling/quartz/MethodInvokingJobDetailFactoryBean.getClassLoader());
setResultMethod = jobExecutionContextClass.getMethod("setResult", new Class[] {
java/lang/Object
});
}
}
}

//方法包装类
public class MethodInvoker
{
public void prepare()
throws ClassNotFoundException, NoSuchMethodException
{
if(staticMethod != null)
{
int lastDotIndex = staticMethod.lastIndexOf('.');
if(lastDotIndex == -1 || lastDotIndex == staticMethod.length())
throw new IllegalArgumentException("staticMethod must be a fully qualified class plus method name: e.g. 'example.MyExampleClass.myExampleMethod'");
String className = staticMethod.substring(0, lastDotIndex);
String methodName = staticMethod.substring(lastDotIndex + 1);
this.targetClass = resolveClassName(className);
this.targetMethod = methodName;
}
Class targetClass = getTargetClass();
String targetMethod = getTargetMethod();
if(targetClass == null)
throw new IllegalArgumentException("Either 'targetClass' or 'targetObject' is required");
if(targetMethod == null)
throw new IllegalArgumentException("Property 'targetMethod' is required");
Object arguments[] = getArguments();
Class argTypes[] = new Class[arguments.length];
for(int i = 0; i < arguments.length; i++)
argTypes[i] = arguments[i] == null ? java/lang/Object : arguments[i].getClass();

try
{
//获取targetClass的targetMethod方法,参数为argTypes
methodObject = targetClass.getMethod(targetMethod, argTypes);
}
catch(NoSuchMethodException ex)
{
methodObject = findMatchingMethod();
if(methodObject == null)
throw ex;
}
}

//反射调用方法
public Object invoke()
throws InvocationTargetException, IllegalAccessException
{
Object targetObject = getTargetObject();
Method preparedMethod = getPreparedMethod();
if(targetObject == null && !Modifier.isStatic(preparedMethod.getModifiers()))
{
throw new IllegalArgumentException("Target method must not be non-static without a target");
} else
{
ReflectionUtils.makeAccessible(preparedMethod);
//执行目标targetObject的目标方法targetMethod,参数为arguments[]
return preparedMethod.invoke(targetObject, getArguments());
}
}
//jobDetails类的方法
public Method getPreparedMethod()
throws IllegalStateException
{
if(methodObject == null)
throw new IllegalStateException("prepare() must be called prior to invoke() on MethodInvoker");
else
return methodObject;
}
public Object getTargetObject()
{
return targetObject;
}
public String getTargetMethod()
{
return targetMethod;
}
private Class targetClass;//目标类
private Object targetObject;//目标实体
private String targetMethod;//目标方法
private String staticMethod;
private Object arguments[];
private Method methodObject;
}

最后再来看一下触发器任务工厂类
//触发器任务工厂类
public class CronTriggerFactoryBean
implements FactoryBean, BeanNameAware, InitializingBean
{

public CronTriggerFactoryBean()
{
jobDataMap = new JobDataMap();
startDelay = 0L;
}

public void afterPropertiesSet()
{
if(name == null)
name = beanName;
if(group == null)
group = "DEFAULT";
if(jobDetail != null)
jobDataMap.put("jobDetail", jobDetail);
if(startDelay > 0L || startTime == null)
startTime = new Date(System.currentTimeMillis() + startDelay);
if(timeZone == null)
timeZone = TimeZone.getDefault();
Class cronTriggerClass;
Method jobKeyMethod;
try
{
cronTriggerClass = ClassUtils.forName("org.quartz.impl.triggers.CronTriggerImpl", getClass().getClassLoader());
jobKeyMethod = org/quartz/JobDetail.getMethod("getKey", new Class[0]);
}
//新建cronTriggerClass的包装类
BeanWrapper bw = new BeanWrapperImpl(cronTriggerClass);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("name", name);
pvs.add("group", group);
if(jobKeyMethod != null)
{
pvs.add("jobKey", ReflectionUtils.invokeMethod(jobKeyMethod, jobDetail));
} else
{
pvs.add("jobName", jobDetail.getName());
pvs.add("jobGroup", jobDetail.getGroup());
}
pvs.add("jobDataMap", jobDataMap);
pvs.add("startTime", startTime);
pvs.add("cronExpression", cronExpression);
pvs.add("timeZone", timeZone);
pvs.add("calendarName", calendarName);
pvs.add("priority", Integer.valueOf(priority));
pvs.add("misfireInstruction", Integer.valueOf(misfireInstruction));
pvs.add("description", description);
//设置CronTrigger属性
bw.setPropertyValues(pvs);
//获取CronTrigger实例
cronTrigger = (CronTrigger)bw.getWrappedInstance();
}
//返回Cron触发器
public CronTrigger getObject()
{
return cronTrigger;
}
public Class getObjectType()
{
return org/quartz/CronTrigger;
}

public boolean isSingleton()
{
return true;
}

public volatile Object getObject()
throws Exception
{
return getObject();
}
private static final Constants constants = new Constants(org/quartz/CronTrigger);
private String name;
private String group;
private JobDetail jobDetail;//job
private JobDataMap jobDataMap;
private Date startTime;
private long startDelay;
private String cronExpression;
private TimeZone timeZone;
private String calendarName;
private int priority;
private int misfireInstruction;
private String description;
private String beanName;
private CronTrigger cronTrigger;
}

//CronTrigger实现类
public class CronTriggerImpl extends AbstractTrigger
implements CronTrigger, CoreTrigger
{
private static final long serialVersionUID = -8644953146451592766L;
protected static final int YEAR_TO_GIVEUP_SCHEDULING_AT;
private CronExpression cronEx;
private Date startTime;
private Date endTime;
private Date nextFireTime;
private Date previousFireTime;
private transient TimeZone timeZone;

static
{
YEAR_TO_GIVEUP_SCHEDULING_AT = CronExpression.MAX_YEAR;
}
}

总结:
[color=green]JobDetailFactoryBean是通过jobDetails属性来生产job;
MethodInvokingJobDetailFactoryBean内置静态类MethodInvokingJob,
而MethodInvokingJob继承了QuartzJobBean,同时与一个内部变量MethodInvoker;
在MethodInvokingJobDetailFactoryBean属性初始化完后,通过MethodInvoker封装TargetObject的TargetMethod方法并在executeInternal中调用MethodInvoker.invoke()来生产job。[/color]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值