因为项目要求根据数据库的配置信息启动Spring中的Quartz的任务,这样就要求CronTriggerBean是动态多样的。搜索了很多文档也没有得其所以然,于是从Spring的配置信息进行入手了。
网上介绍的各种例子中,默认都是以SchedulerFactoryBean进行开始的,也看到,里面就一个参数就是triggers,那么这样就好说了,只要把trigger根据数据库中的配置信息进行生成就好了。
<bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="doTime"/> </list> </property> </bean>
伪代码就是这样的,写个类继承SchedulerFactoryBean
XXXvo = queryDB(); CronTriggerBean bean = new CronTriggerBean(); bean.setBeanName("beanNameFileSchedule"); bean.setCronExpression(xxxvo.getCronExpression()); jobDetailFactoryBean.setArguments(new Object[] { XXX}); bean.setJobDetail((JobDetail) jobDetailFactoryBean.getObject()); bean.afterPropertiesSet(); this.setTriggers((CronTriggerBean[]) this.triggerBeanList .toArray(new CronTriggerBean[0])); this.afterPropertiesSet();
这样基本上就大功告成了,但是调试过程中的小问题却不少。
第一:CronTriggerBean和SchedulerFactoryBean都实现了InitializingBean接口,这样的话,需要在两个类的设置完属性之后,需要手动的调用afterPropertiesSet的方法。
第二:CronTriggerBean需要设置BeanName,原因看一下CronTriggerBean方法的afterPropertiesSet就知道了,quartz的trigger如果没有Name的话,就会报出来错误。
第三:Schedule的执行类配置到了Spring的XML中,但又因Schedule的执行类的执行方法有参数,这个参数又是动态传入的。这样的一个问题就是在SchedulerFactoryBean中调用下面的方法【jobDetailFactoryBean.setArguments(new Object[] { XXX});】设置参数的时候就已经晚了,因为Spring在实例化MethodInvokingJobDetailFactoryBean的时候就会报出来找不到方法的错误。现在的处理方式就是先在XML中为MethodInvokingJobDetailFactoryBean配置一个假的参数进去,只是为了占据类型,然后在SchedulerFactoryBean中重新设置一遍,设置完成后,不能忘记调用afterPropertiesSet()方法,不然trigger不起作用。
写的稍微乱了一些,就先记录下来吧,后续再整理了。