`
Donald_Draper
  • 浏览: 981185 次
社区版块
存档分类
最新评论

JobDetailFactoryBean与MethodInvokingJobDetailFactoryBean源码分析

 
阅读更多
Spring与Quartz集成详解:http://donald-draper.iteye.com/blog/2323591
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;
    }
}

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

相关推荐

    Spring整合Quartz分布式调度的示例代码

    然后,需要配置Job,提供了两种方式来配置Job,分别是MethodInvokingJobDetailFactoryBean和JobDetailFactoryBean。MethodInvokingJobDetailFactoryBean用于调用特定bean的一个方法,而JobDetailFactoryBean更加灵活...

    spring quartz 集群模式

    Spring通过`org.springframework.scheduling.quartz`包提供了对Quartz的API封装,包括`SchedulerFactoryBean`、`JobDetailFactoryBean`和`TriggerFactoryBean`等,使得我们可以用声明式的方式定义任务和触发器。...

    spring整合quartz常见问题

    Spring与Quartz的集成是企业级应用中非常常见的技术组合之一。Quartz是一个功能强大的作业调度框架,而Spring则是Java领域中广泛使用的轻量级控制反转(IoC)容器。两者结合能够提供灵活、高效的任务调度解决方案。 #...

    spring+quartz需要的4个jar包 不需要6个

    4. **数据库驱动**(可选):根据你使用的数据库类型,可能需要相应的JDBC驱动,例如`mysql-connector-java.jar` - 如果你的任务需要与数据库交互,这将是必不可少的。 通常,有人可能会上传6个jar包,可能是因为...

    Quartz与Spring2.0整合Eclipse例程

    &lt;bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"&gt; ``` 在Eclipse中,你可以通过右键点击项目,选择`Run As` -&gt; `Java Application`来启动项目。由于你提到...

    Spring + quartz

    标题 "Spring + quartz" 暗示了我们讨论的主题是关于如何在Java应用程序中...结合源码分析和工具使用,可以更深入地理解它们的工作原理和优化策略。在实际项目中,这样的组合能够极大地提升系统的自动化水平和效率。

    quartz-2.2.2-distribution.rar

    描述中提到 "quartz-2.2.2-版本+springboot2.x" 暗示了这个压缩包不仅包含 Quartz 框架,还特别强调了与 Spring Boot 2.x 的兼容性。Spring Boot 是一个简化 Spring 应用程序开发的框架,提供了一种快速构建可执行...

    spring+quartz定时任务

    Spring框架提供了与Quartz库集成的能力,使得我们可以方便地创建和管理定时任务。 Spring与Quartz的集成主要基于Spring的`TaskExecution`和`TaskScheduling`模块,它允许我们以声明式的方式配置定时任务,同时也...

    Quartz Spring整合——附带webservice Demo

    9. **源码分析**:标签中提到的 "源码" 暗示这个示例可能包含了对这些库的深入理解和使用,或者提供了自定义的扩展。 综上所述,这个示例不仅展示了如何在 Spring 应用中集成和使用 Quartz 定时任务,可能还包括了 ...

    spring-context-support.jar,quartz-all-1.6.0.jar

    此外,Spring还提供了一个`org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean`,可以直接通过指定目标对象和方法来创建`Job`,这样就不需要显式实现`Job`接口。这种方法对于简单的任务来说...

    maven_spring_quartz.rar

    同时,Spring的`MethodInvokingJobDetailFactoryBean`允许你直接调用一个Spring Bean的方法作为定时任务,这进一步提高了灵活性。 总的来说,Spring与Quartz的集成使任务调度变得简单易行。通过Spring的IoC和AOP...

    springMVC和Quartz定时

    它提供了模型-视图-控制器(MVC)架构,帮助开发者将业务逻辑与表现层分离,提高了代码的组织性和可测试性。而Quartz是Java领域内广泛应用的定时任务库,能够实现定时调度任务,广泛应用于大数据处理、定时报告生成...

    Spring-quartz实现定时器(含代码)

    Quartz则是一个强大的、开放源码的作业调度框架,它允许开发者精确地安排任务执行时间。Quartz支持复杂的调度策略,如按时间间隔执行、在特定日期执行等。 **整合Spring和Quartz** 1. **引入依赖**:在你的`pom....

    spring timer、quartz俩种任务调度

    Spring框架可以通过`org.springframework.scheduling.quartz`包与Quartz进行集成。下面是一个使用Quartz的例子: ```java import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz....

    schedule.zip

    在本文中,我们将深入探讨Spring Boot中的定时任务,包括如何使用Spring Boot...结合提供的源码资料,你将能更深入地理解和应用这些技术。实践是检验真理的唯一标准,动手尝试编写和调试代码,你的技能将得到显著提升。

    Spring_QuartZDemo

    通过分析这个项目,你可以深入理解Spring与Quartz的集成方式,以及如何在实际应用中利用它们来实现复杂的定时任务需求。 此外,Quartz还支持JobGroup(任务组)、TriggerGroup(触发器组)、JobDataMap(用于传递...

    quartz-1.6.4

    通过分析源码,开发者可以深入理解其内部工作机制,包括任务调度算法、数据库操作、触发器管理等方面,这对于定制化开发或优化性能非常有帮助。 总结来说,Quartz是一个强大的作业调度框架,它的1.6.4版本提供了...

    ssm-springMVC-整合Quartz(解决了无法注入service问题)-项目示例

    当需要在Quartz作业中调用由Spring管理的服务时,会出现依赖注入的问题,因为Quartz的工作线程与Spring的ApplicationContext不一致。 为了解决这个问题,我们需要以下步骤: 1. **配置Spring上下文**:首先,在...

    java网上爬虫和定时任务

    Java网上爬虫与定时任务是IT领域中两个重要的技术方向,它们在数据分析、信息收集以及自动化运维等方面有着广泛的应用。本篇文章将详细讲解如何利用Java实现网上爬虫以及结合Quartz实现定时任务。 首先,我们要了解...

    spring定时器

    Spring与Quartz的集成使得我们可以利用Spring的依赖注入(DI)和AOP特性来更方便地管理定时任务。 首先,我们需要理解Spring定时器的基本概念。Spring Task提供了一个简单的API,允许我们定义和管理定时任务,包括`...

Global site tag (gtag.js) - Google Analytics