转载自 https://blog.youkuaiyun.com/leocnx/article/details/54573275
背景:
在quartz job 里调用spring 容器管理的bean,出现空指针异常,即没有注入成功,在网上搜了很多类似的问题,最终发现都是copy改,经过各种折腾算是解决了问题。
解决方法有两种:
第一种方式:不去继承QuartzJobBean,只是一个独立的job bean,通过配置MethodInvokingJobDetailFactoryBean来实现;
第二种方式:继承QuartzJobBean,但是要重写SchedulerFactoryBean的jobFactory。
首先说明下版本:
- <spring.version>4.0.2.RELEASE</spring.version>
- <quartz.version>2.2.2</quartz.version>
代码结构如下:
说明:
MyJobAlone为不用继承方式实现的job bean
MyJobExtend为使用继承方式实现的job bean
MyQuartzJobFactory为重写的jobFactory,用于实现在使用继承方式时注入spring管理的bean
SayServiceImpl为spring 管理的bean
-SayService.java
- package top.auok.quartz.bean;
- public interface SayService {
- void sayHello();
- }
-SayServiceImpl.java
- package top.auok.quartz.bean;
- import org.springframework.stereotype.Service;
- @Service("sayService")
- public class SayServiceImpl implements SayService {
- @Override
- public void sayHello() {
- System.out.println("hello, i'm invoked by quartz.");
- }
- }
-applicationContext.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.1.xsd
- http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
- <context:component-scan base-package="top.auok.quartz" />
- </beans>
applicationContext-quartz-alone.xml为非继承方式的配置文件
applicationContext-quartz-extend.xml为继承方式的配置文件
第一种方式:(非继承)
1.job bean - MyJobAlone.java代码如下:
- package top.auok.quartz;
- import javax.annotation.Resource;
- import org.springframework.stereotype.Component;
- import top.auok.quartz.bean.SayService;
- @Component("myJobAlone")
- public class MyJobAlone {
- @Resource
- private SayService sayService;
- public void execute() {
- sayService.sayHello();
- }
- }
2.配置 - applicationContext-quartz-alone.xml:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.1.xsd
- http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
- <!-- jobDetail -->
- <bean id="aloneJobDetail"
- class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
- <property name="targetObject">
- <ref bean="myJobAlone" />
- </property>
- <property name="targetMethod">
- <value>execute</value>
- </property>
- </bean>
- <!-- trigger -->
- <bean id="aloneTrigger"
- class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
- <property name="jobDetail" ref="aloneJobDetail"></property>
- <property name="cronExpression" value="0/2 * * * * ?"></property>
- </bean>
- <!-- schedule factory -->
- <bean id="SpringJobSchedulerFactoryBean"
- class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
- <property name="triggers">
- <list>
- <ref bean="aloneTrigger" />
- </list>
- </property>
- </bean>
- </beans>
第二种方式:(继承)
1.job bean - MyJobExtend.java代码如下:
- package top.auok.quartz;
- import javax.annotation.Resource;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.springframework.scheduling.quartz.QuartzJobBean;
- import top.auok.quartz.bean.SayService;
- public class MyJobExtend extends QuartzJobBean {
- @Resource
- private SayService sayService;
- @Override
- protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
- sayService.sayHello();
- }
- }
2.jobFactory - 重写 -MyQuartzJobFactory.java
- package top.auok.quartz;
- import org.quartz.spi.TriggerFiredBundle;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
- import org.springframework.scheduling.quartz.SpringBeanJobFactory;
- import org.springframework.stereotype.Component;
- @Component("myQuartzJobFactory")
- public class MyQuartzJobFactory extends SpringBeanJobFactory {
- @Autowired
- private AutowireCapableBeanFactory beanFactory;
- /**
- *
- * 这里覆盖了super的createJobInstance方法,对其创建出来的类再进行autowire。
- *
- */
- @Override
- protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
- Object jobInstance = super.createJobInstance(bundle);
- beanFactory.autowireBean(jobInstance);
- return jobInstance;
- }
- }
3.配置 - applicationContext-quartz-extend.xml:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.1.xsd
- http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
- <!-- jobDetail -->
- <bean id="extendJobDetail"
- class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
- <property name="jobClass" value="top.auok.quartz.MyJobExtend" />
- <property name="durability" value="true" /> <!-- Jobs added with no trigger must be durable -->
- </bean>
- <!-- trigger -->
- <bean id="extendTrigger"
- class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
- <property name="jobDetail" ref="extendJobDetail"></property>
- <property name="cronExpression" value="0/2 * * * * ?"></property>
- </bean>
- <!-- schedule factory -->
- <bean id="SpringJobSchedulerFactoryBean"
- class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
- <property name="triggers">
- <list>
- <ref bean="extendTrigger" />
- </list>
- </property>
- <property name="jobFactory" ref="myQuartzJobFactory"></property>
- </bean>
- </beans>
调试运行:
- package top.auok.quartz;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class App {
- public static void main(String[] args) {
- // init spring ioc container
- new ClassPathXmlApplicationContext("applicationContext.xml", "applicationContext-quartz-extend.xml"); //按需更改配置文件alone/extend
- }
- }
the end
附:pom.xml
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>top.auok</groupId>
- <artifactId>quartz</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>quartz</name>
- <url>http://maven.apache.org</url>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <spring.version>4.0.2.RELEASE</spring.version>
- <slf4j.version>1.7.7</slf4j.version>
- <log4j.version>1.2.17</log4j.version>
- <quartz.version>2.2.2</quartz.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
- <version>${quartz.version}</version>
- </dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <version>${log4j.version}</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>${slf4j.version}</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <version>${slf4j.version}</version>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>2.0.2</version>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- <encoding>utf8</encoding>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </project>
代码下载