通过Spring来管理Quartz相对来说比较简单,可查的文档很多,也有相似很多的成功案例。但是偏偏到我这儿就不行了,人倒霉的时候,喝水都塞牙缝。。。
要使用Quartz,首先我们来简单弄清楚Quartz的三个概念
- Job - 简单点说就是需要执行的逻辑
- Trigger - Job什么时候执行,由Cron表达式来定义执行时间,比如0 0 0 * * ? 表示每天0点开始执行
以下是我的配置,三个Bean,前两个和Quartz的两个概念对应,第三个是启动器,在Web容器启动的时候就会启动Quartz。
abcService是配置的一个bean, 里面没有任何和Quartz相关的东西,在这个配置中Spring对其做了代理。
1: <bean id="abcJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">2: <property name="targetObject" ref="abcService" />3: <property name="targetMethod" value="abcMethod" />4: <property name="arguments"><list> list> property>5: <property name="concurrent" value="false" />6: bean>
7:8: <bean id="abcTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">9: <property name="jobDetail" ref="abcJobDetail" />10:
11: <property name="cronExpression" value="0 0 0 * * ?" />12: bean>
13:14: <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no">15: <property name="triggers">16: <list>17: <ref bean="abcTrigger" />18: list>
19: property>
20: bean>
基本参考往上和官方文档。
但是意外往往就发生在最容易疏忽的地方,如果没有上面第4行(高亮行),系统就是跑不起来,抛出NoSuchMethodException,这不是坑人吗?
我查了其他成功案例,都是这么配的啊,官方文档也是没有第4行的?算了,直接看源代码。
调试的时候发现Spring 将所有的Bean作为参数去调用我定义的方法(abcMethod),当然找不到啦,加上第4行,强制告诉MethodInvokingJobDetailFactoryBean,我这个方法没参数,不用给我随便加,真怀疑别人怎么跑起来的(对了,我的Spring是2.5.6,如有知情者请告知,在此先谢谢了)。
附MethodInvokingJobDetailFactoryBean源码( 其实在这个类中调用MethodInvoker.prepare()方法的部分代码)
1: Class targetClass = getTargetClass();2: String targetMethod = getTargetMethod();3: if (targetClass == null) {4: throw new IllegalArgumentException("Either 'targetClass' or 'targetObject' is required");5: }6: if (targetMethod == null) {7: throw new IllegalArgumentException("Property 'targetMethod' is required");8: }9:10: Object[] arguments = getArguments();11: Class[] argTypes = new Class[arguments.length];
12: for (int i = 0; i < arguments.length; ++i) {13: argTypes[i] = (arguments[i] != null ? arguments[i].getClass() : Object.class);14: }15:16: // Try to get the exact method first.
17: try {
18: this.methodObject = targetClass.getMethod(targetMethod, argTypes);
19: }
第十行拿到的arguments居然是我所有配置过的Bean,真不知道为什么。