Spring Boot定时任务-Job类对象注入

如何在我们的任务类当中,去完成其他对象的注入,Job类中注入对象,回到我们的代码当中,这个是我们编写的

Job类,比如我们在Job类当中呢,我要使用到我业务下某个类的某个方法,那我们是不是要将我们业务层的对象

注入到这当中,那我们怎么去注入呢,首先我们来编写一个业务代码,现在我就直接编写一个业务类了

@Service
public class UsersService {

	public void addUsers(){
		System.out.println("Add Users......");
	}
}

然后在这里加一个@Service,在这里加一个方法addUsers,在这里我们去打印呢一句话,然后在我们的

QuartzDemo5下,那我们就用一下@Autowired,这样我们就完成了一个注入

public class QuartzDemo2 implements Job {
	
	@Autowired
	private UsersService usersService;
	
	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		System.out.println("Execute...."+new Date());
		this.usersService.addUsers();
	}
}

然后在这个方法里我再加一句话,通过usersService去调用它的addUsers方法,比较简单,那我们加完以后,

看能不能将我们的UserService注入进来,我们找到启动类,去运行,观察一下控制台,这个时候就有异常出现了,而且报的

是空指针异常,是哪一行报的呢,是这一行

this.usersService.addUsers();

这一行报空指针,说明什么,我们这个userService没有注入进来,那么我们分析一下,他为什么没有将UserService

注入进来呢,我们还得看一下QuartzConfig这个类,我提供了一个方法,这个方法能够返回JobDetailFactoryBean,

然后我创建了一个JobDetailFactoryBean,并且我在这个对象下,去调用一个setJobClass,把我们的QuartzDemo2

的class,也就是这个对象的实例化完全交给JobDetailFactoryBean他来处理了,那么他是怎么实例化的呢,我们可以

看一下源码,其实JobDetailFactoryBean在实例QuartzDemo2对象的时候,实例化我们的任务类的时候,他用的是

org.springframework.scheduling.quartz.AdaptableJobFactory

这个类下的一个方法,叫createJobInstance

/**
 * Create an instance of the specified job class.
 * <p>Can be overridden to post-process the job instance.
 * @param bundle the TriggerFiredBundle from which the JobDetail
 * and other info relating to the trigger firing can be obtained
 * @return the job instance
 * @throws Exception if job instantiation failed
 */
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
	return bundle.getJobDetail().getJobClass().newInstance();
}

我们看一下这个方法,其实这个方法比较简单,在这里就是把我们的类拿到,然后调了一个newInstance,这是什么意思呢,

他对我们传过来类的实例化方式,采用的就是反射的机制来实例化,那么他用反射,就意味着我们现在这个对象的实例化,

并没有经过Spring的处理,如果没有被Spring实例化,那么就意味着在Spring的IOC容器当中,就没有QuartzDemo2这个对象,

没有这个对象,那他肯定是无法完成注入,因为Spring的注入是要求注入的对象和被注入的对象,都必须在Spring的IOC

容器里存在,这样才能完成对象的注入,这是他的一个要求,所以说现在呢,我们可以看到,正因为他并不是Sping去实例化的,

这个这个过程,而是通过JobDetailFactoryBean,他这里的一个方法来完成实例化的,是通过反射的,所以这个对象是无法注入的,

那么这个问题已经找到了,接下来我们看怎么解决,其实对于这个问题的解决方案,我们可以采用这样的一种方式去做,我编写一个

类,然后我也去继承AdaptableJobFactory,然后在这个继承的过程当中,我去重写createJobInstance方法,重写的目的是什么呢,

你现在把这个对象创建完,先别返回,先别着急返回,我在这个方法当中呢,先将你创建的对象,手动的添加到IOC的容器当中,

并且去完成注入,这样是不是就可以把QuartzDemo里面userService就给注入进来了,这是我们解决问题的一个方式,我们来看

怎么去实现,在这里我们需要去继承这个类,我们写一个class,就叫MyAdaptableJobFactory

@Component("myAdaptableJobFactory")
public class MyAdaptableJobFactory extends AdaptableJobFactory {

	//AutowireCapableBeanFactory 可以将一个对象添加到SpringIOC容器中,并且完成该对象注入
	@Autowired
	private AutowireCapableBeanFactory autowireCapableBeanFactory;
	
	/**
	 * 该方法需要将实例化的任务对象手动的添加到springIOC容器中并且完成对象的注入
	 */
	@Override
	protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
		Object obj = super.createJobInstance(bundle);
		//将obj对象添加Spring IOC容器中,并完成注入
		this.autowireCapableBeanFactory.autowireBean(obj);
		return obj;
	}

}

然后让他去继承AdaptableJobFactory,然后我在这里去重写createJobInstance方法,然后你这个方法该去创建还是去创建,

只是创建完了别返回,他创建完了会返回一个Object对象,现在创建完这个对象以后,我在返回之前,是不是要将他加入到Spring

的IOC容器中,并且完成注入,这里先把方法说明一下,该方法需要将实例化的任务对象,手动的添加到SpringIOC容器中,并且完成对象

的注入,那么我们怎么把他放到SpringIOC的容器里,并且完成注入呢,这个时候我们需要依赖于另一个对象,所以在这里我先去注入

一个对象,这个对象是谁呢,他的名字叫AutowireCapableBeanFactory,需要这样的一个对象,在这里我们来解释一下这个对象的

作用,其实这个对象的作用呢,就是将我们的对象,可以将一个对象添加到SpringIOC的容器中,并且完成该对象的注入,也就是说你

通过这个对象,把一个bean对象,它会把它放到Spring的IOC容器当中,所有需要注入的过程,做一个注入处理,那我们在这里

就用到这个对象了,

将obj对象=添加到Spring IOC容器中,并完成注入,那怎么去做呢,我们需要调用它的一个方法,这个方法叫什么呢,叫autowireBean,

在这里我们把谁放到里面呢,把obj放到里面,就会把userService完成注入的操作,这样我们一个类就写好了,你这个类要想真正的能用,

你是不是要把它实例化出来,那靠谁实例化呢,这肯定还得依赖于Spring,所以我们在这里加一个@Component,加一个这个注解,

然后在这里可以给对象起一个id,这个大家应该懂什么意思,那么这个类写完了我们怎么去用呢,产生异常的原因我们不写了,

因为我们分析完了,然后编写一个类,编写一个MyAdaptableJobFactory,解决该问题,这样就可以解决了吗,很显然还是不允许,

还得多一个步骤,回到我们的QuartzConfig当中,我们注意SchedulerFactoryBean对象,这个是完成Trigger的一个设置,那其实

这个对象除了可以设置一个Trigger以外,他还可以重新设置AdaptableJobFactory,允许你新的设置AdaptableJobFactory,

怎么去设置呢

@Bean
public SchedulerFactoryBean schedulerFactoryBean(
			CronTriggerFactoryBean cronTriggerFactoryBean,
			MyAdaptableJobFactory myAdaptableJobFactory){
	SchedulerFactoryBean factory = new SchedulerFactoryBean();
	//关联trigger
	factory.setTriggers(cronTriggerFactoryBean.getObject());
	factory.setJobFactory(myAdaptableJobFactory);
	return factory;
}

在这个对象下他有一个方法,叫setJobFactory,允许你重新设置一个job工厂,那其实我们现在要做的事,通过Spring创建的

myAdaptableJobFactory拿过来,交给他,让他去调用createJobInstance,并且将对象放到IOC容器当中,同时完成注入,

那么怎么去交给他呢,需要注入,再这个方法当中再去注入一个参数,MyAdaptableJobFactory myAdaptableJobFactory,

这个参数的名称叫什么呢,就可以用我们定义的字符串myAdaptableJobFactory,就把这个对象交到SchedulerFactoryBean

当中,他就可以去调用我们的createJobInstance,完成对象的实例化,这是最后一步,修改QuartzConfig类,关键的一点就是,

关键就是能够返回SchedulerFactoryBean,我们再添加一个参数,关键是MyAdaptableJobFactory他的一个定义,然后就是

setJobFactory方法,把这个对象set进去,接下来我们来测试一下,我们这种解决问题的方式能不能解决问题,我们启动main

方法,启动类去run一下,我们可以看到控制台输出的结果是没有问题的,我们的定时任务方法执行了,同时addUser执行了,

addUser不就是userService里面的东西吗,所以这种方式是可以解决这个问题的,可能大家觉得这种方式可能会比较繁琐,

倒不是那么很繁琐,要明白他的含义,我们做个总结吧,最关键的一点就是,在给你实例化Job对象的时候,我们的QuartzDemo2,

在实例化对象的时候,并没有通过Spring,没有通过Spring完成IOC的注入,那么我们解决问题的方式呢,重写回到我们的这个类的时候,

调的一个方法,这个方法位于

org.springframework.scheduling.quartz.AdaptableJobFactory

然后重写它的createJobInstance方法,最关键的一点就是,我们把它所实例化的一个对象,拿过来,通过我们使用的一个叫

AutowireCapableBeanFactory,来手动的把它加入到IOC容器当中,并且完成一个属性的注入,属性注入就是UsersService

的一个注入,然后我们要将类实例化出来怎么办呢,上面加一个注解@Component("myAdaptableJobFactory"),实例化出来之后

怎么去用呢,回到我们的QuartzConfig当中,在返回SchedulerFactoryBean的方法当中,加一个参数,把我们的参数加到里面,

一个方法的的注入,在这里通过SchedulerFactoryBean对象,调用setJobFactory,把我们新的创建对象myAdaptableJobFactory,

我们对象实例化的一个工厂,交给他,他来调用createJobInstance,完成对象的一个实例化,同时加入到SpringIOC并完成注入,

这样我们的QuartzDemo2的usersService就有值了,这是他解决问题的一个流程
<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>com.learn</groupId>
  <artifactId>spring-boot-quartz</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.12.RELEASE</version>
  </parent>
  
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>
  
  <dependencies>
  	<!-- springBoot的启动器 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 添加Scheduled坐标 -->
    <!-- <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
    </dependency> -->
	<!-- Quartz坐标 -->
	<!-- <dependency>
		<groupId>org.quartz-scheduler</groupId>
		<artifactId>quartz</artifactId>
		<version>2.2.1</version>
	</dependency> -->
	<!-- Quartz坐标 -->
	<dependency>
		<groupId>org.quartz-scheduler</groupId>
		<artifactId>quartz</artifactId>
		<version>2.2.1</version>
		<exclusions>
			<exclusion>
				<artifactId>slf4j-api</artifactId>
				<groupId>org.slf4j</groupId>
			</exclusion>
		</exclusions>
	</dependency>
	<!-- 添加Scheduled坐标 -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context-support</artifactId>
	</dependency>
	<!-- Sprng tx 坐标 -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-tx</artifactId>
	</dependency>
  </dependencies>
</project>
package com.learn.config;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;

@Component("myAdaptableJobFactory")
public class MyAdaptableJobFactory extends AdaptableJobFactory {

	//AutowireCapableBeanFactory 可以将一个对象添加到SpringIOC容器中,并且完成该对象注入
	@Autowired
	private AutowireCapableBeanFactory autowireCapableBeanFactory;
	
	/**
	 * 该方法需要将实例化的任务对象手动的添加到springIOC容器中并且完成对象的注入
	 */
	@Override
	protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
		Object obj = super.createJobInstance(bundle);
		//将obj对象添加Spring IOC容器中,并完成注入
		this.autowireCapableBeanFactory.autowireBean(obj);
		return obj;
	}

}
package com.learn.quartz;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;

import com.learn.service.UsersService;

/**
 * Job类
 */
public class QuartzDemo2 implements Job {
	
	@Autowired
	private UsersService usersService;
	
	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		System.out.println("Execute...."+new Date());
		this.usersService.addUsers();
	}
}
package com.learn.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.learn.quartz.QuartzDemo2;

/**
 * Quartz配置类
 * @author Leon.Sun
 *
 */
@Configuration
public class QuartzConfig {

	
	/**
	 * 1.创建Job对象
	 */
	@Bean
	public JobDetailFactoryBean jobDetailFactoryBean(){
		JobDetailFactoryBean factory = new JobDetailFactoryBean();
		//关联我们自己的Job类
		factory.setJobClass(QuartzDemo2.class);
		return factory;
	}
	
	/**
	 * 2.创建Trigger对象
	 * 简单的Trigger
	 */
//	@Bean
//	public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
//		SimpleTriggerFactoryBean factory = new SimpleTriggerFactoryBean();
//		//关联JobDetail对象
//		factory.setJobDetail(jobDetailFactoryBean.getObject());
//		//该参数表示一个执行的毫秒数
//		factory.setRepeatInterval(2000);
//		//重复次数
//		factory.setRepeatCount(5);
//		return factory;
//	}
	
	/**
	 * Cron Trigger
	 */
	@Bean
	public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
		CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
		factory.setJobDetail(jobDetailFactoryBean.getObject());
		//设置触发时间
		factory.setCronExpression("0/2 * * * * ?");
		return factory;
	}
	
//	@Bean
//	public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean){
//		SchedulerFactoryBean factory = new SchedulerFactoryBean();
//		//关联trigger
//		factory.setTriggers(simpleTriggerFactoryBean.getObject());
//		
//		return factory;
//	}
	
	/**
	 * 3.创建Scheduler对象
	 */
	@Bean
	public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean,MyAdaptableJobFactory myAdaptableJobFactory){
		SchedulerFactoryBean factory = new SchedulerFactoryBean();
		//关联trigger
		factory.setTriggers(cronTriggerFactoryBean.getObject());
		factory.setJobFactory(myAdaptableJobFactory);
		return factory;
	}
}
package com.learn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * 
 *spring Boot 整合Quartz案例
 *
 */
@SpringBootApplication
@EnableScheduling
public class QuartzApp {

	public static void main(String[] args) {
		SpringApplication.run(QuartzApp.class, args);
	}
}
package com.learn.service;

import org.springframework.stereotype.Service;

@Service
public class UsersService {

	public void addUsers(){
		System.out.println("Add Users......");
	}
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是Spring Boot整合Quartz的基本步骤: 1. 添加依赖:在pom.xml文件中添加Quartz和Spring Boot Starter Quartz的依赖。 ```xml <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> ``` 2. 创建Job类:创建一个实现了org.quartz.Job接口的Job类,实现Job接口的execute方法。 ```java public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // Job执行的具体逻辑 } } ``` 3. 创建Trigger和JobDetail:创建JobDetail和Trigger,并将JobDetail和Trigger绑定在一起。 ```java // 创建JobDetail实例,并指定任务名称、组名、以及任务执行类 JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("job1", "group1").build(); // 创建Trigger实例,每秒钟执行一次 Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow() .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()).build(); // 将Job和Trigger关联起来 scheduler.scheduleJob(job, trigger); ``` 4. 配置SchedulerFactoryBean:配置SchedulerFactoryBean,使得Spring Boot能够自动注入SchedulerFactoryBean实例。 ```java @Configuration public class SchedulerConfig { @Autowired private JobFactory jobFactory; @Bean public SchedulerFactoryBean schedulerFactoryBean() { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); schedulerFactoryBean.setJobFactory(jobFactory); return schedulerFactoryBean; } @Bean public Scheduler scheduler() { return schedulerFactoryBean().getScheduler(); } } ``` 5. 启动应用程序:在Spring Boot应用程序启动后,SchedulerFactoryBean实例会自动启动,开始执行定时任务。 ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 以上就是Spring Boot整合Quartz的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值