您的位置:首页 > 编程语言 > Java开发

Spring4.X+Quartz2.X无法自动注入bean问题

2016-10-05 23:38 471 查看
Quartz是目前非常流行的任务框架,一般用来做定时任务。

但是在QuartzJobBean中无法使用注解自动注入bean。

需要达到的效果:

@Resource
private  IAlumniService alumniService;


原因是因为Job对象的实例化过程是在Quartz中进行的,bean是在Spring容器当中的,那么如何将他们关联到一起呢?

Quartz提供了JobFactory接口,让我们可以自定义实现创建Job的逻辑。那么我们通过实现JobFactory 接口,在实例化Job以后,在通过ApplicationContext 将Job所需要的属性注入即可。

重写JobFactory

/**
* Created by XFL.
* time on 2016/10/4 23:13
* description:自定义JobFactory以便在JobBean中可以获取Spring注解的bean
*/
public class MyJobFactory extends AdaptableJobFactory {
/**
* 这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.
*/
private AutowireCapableBeanFactory capableBeanFactory;

/**
* 注入capableBeanFactory.
* @param capableBeanFactory AutowireCapableBeanFactory
*/
@Autowired
public MyJobFactory(final AutowireCapableBeanFactory capableBeanFactory) {
Assert.notNull(capableBeanFactory, "自动注入AutowireCapableBeanFactory失败");
this.capableBeanFactory = capableBeanFactory;
}
/**
* 重写该方法,以便在quartz中可以获取注解的bean.
* @param bundle TriggerFiredBundle
* @return 返回实例(Spring bean)
* @throws Exception 异常
*/
protected final Object createJobInstance(
final TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
//进行注入,这属于Spring的技术,不清楚的可以查看Spring的API.
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}


Spring-quartz配置文件,这里只考虑单机部署,未考虑集群,分布式部署。如需要集群部署需要更改此文件,在bean quartzScheduler中需要加入datascore,quartz集群配置文件等等。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="quartzScheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory" ref="myJobFactory"/>
<property name="triggers">
<list>
<ref bean="trigger" />
</list>
</property>
</bean>
<!--任务-->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.jxufe.schedule.task.QuartzTestJobBean"/>
<property name="durability" value="true" />
<property name="requestsRecovery" value="true" />
</bean>
<!--触发器-->
<bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail" />
<property name="cronExpression" value="0 0/5 * * * ?" />
</bean>
<bean id="myJobFactory" class="com.jxufe.schedule.task.MyJobFactory"/>
</beans>


任务

public class QuartzTestJobBean extends QuartzJobBean {
/**
* Log4j2 日志对象.
*/
private static final Logger logger = LogManager.getLogger(QuartzTestJobBean.class);
/**
* 注入alumniService.
*/
@Resource
private  IAlumniService alumniService;

/**
* 测试定时任务.
* @param jobExecutionContext 定时任务
* @throws JobExecutionException 抛出异常
*/
@Override
protected final void executeInternal(final JobExecutionContext jobExecutionContext) throws JobExecutionException {
logger.info("执行定时任务QuartzTestJobBean");
System.out.println("执行定时任务");

//  SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
Map<String, Object> parameterMap = new HashMap<>();
//获取bean
if (alumniService != null) {
List<Map<String, Object>> result = alumniService.findAlumni(parameterMap);
if (result != null) {
logger.info("获取的大小" + result.size());
}
}

logger.info("执行定时任务完毕QuartzTestJobBean");
}
}


还有一种解决办法是在任务中加入,使用这种方法可以不需要重写JobFactory

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);


注意:以上方法如果使用构造函数注入,是仍然不行的

使用到的框架包

Spring基础包,SpringMVC框架包

spring-context-support,quartz,quartz-jobs
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring quartz