Quartz入门看这一篇文章就够了

news2025/1/17 0:49:20

第一章 Quartz简介

第一节 Quartz是什么?

1
Quartz [kwɔːts]是一个完全由Java编写的开源的作业调度框架

第二节 Quartz可以用来做什么?

  • 比如说买火车票下单之30分钟之后,查看是否付款
  • 付款完成之后,在乘车日期的时候是否乘车
  • 或者每个月1号扣房贷
  • 每个月20号自动还信用卡
  • 想定时在某一个时间,在到了那个时间的时候去执行某个任务

第二章 快速入门

第一节 常用API介绍

  • Job接口
    1
    
    首先我们需要定义实现一个定时功能的接口,我们可以称之为Task(或Job)如定时发送邮件的task(Job)重启机器的task(Job)优惠券到期发送短信提醒的task(Job)
    

     

  • Trigger [ˈtrɪɡə(r)] 触发器
    1
    
    有了任务之后,还需要一个能够实现触发任务去执行的触发器,触发器Trigger最基本的功能是指定Job的执行时间,执行间隔,运行次数等
    

     

  • Scheduler [ˈʃɛdjuːlə]调度器
    1
    
    有了Job和Trigger后,怎么样将两者结合起来呢?即怎样指定Trigger去执行指定的Job呢?这时需要一个Schedule,来负责这个功能的实现
    

     

1
2
3
4
上面三个是Quartz的基本组成部分
1. 调度器: Scheduler
2. 任务:   Job,以及JobDetail
3. 触发器: Trigger,包括SimpleTrigger和CronTrigger

第二节 简单使用(API)

2.1 添加依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.0</version>
</dependency>

2.2 简单代码

  • 自定义一个任务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    /**
     * 创建一个被执行的任务
     */
    public class HelloJob implements Job{
    	@Override
    	public void execute(JobExecutionContext context) throws JobExecutionException {
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		System.out.println("任务被执行...."+sdf.format(new Date()));
    	}
    }
    
  • 启动任务,并设置每5秒执行一次

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    public static void main(String[] args) throws SchedulerException{
    	//1.创建自定义的任务(job)对象
    	JobDetail job = JobBuilder.newJob(HelloJob.class).build();
    	//2.创建触发器(Trigger)对象,并设置触发规则,每格五秒触发一次Job
    	Trigger trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).build();
    	//3.创建任务调度(Scheduler)对象
    	Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
    	//4.将任务和触发器联系到一起
    	scheduler.scheduleJob(job, trigger);
    	//5.启动任务
    	scheduler.start();
    }
    

    2.3 核心对象介绍

  • JobDetail

    1
    
    JobDetail内部指定了Job的更详细的属性,比如说任务名称,任务群组等
    
  • Trigger

    1
    
    一个类,用于描述触发Job执行的时间规则
    
    • SimpleTrigger
      1
      
      一次或者固定时间间隔周期的触发规则
      
    • CronTrigger
      1
      
      通过cron表达式描述出更为复杂的触发规则
      
  • Scheduler

    1
    2
    3
    4
    5
    
    1. 代表一个Quartz的独立运行容器
    2. Trigger和JobDetail被注册到Scheduler中
    3. 二者在Scheduler中拥有各自的名称(name)和组名(group)
    4. Trigger和JobDetail的名称和组名的组合必须唯一,但是Trigger的名称和组名的组合可以和JobDetail的相同,因为它们类型不同
    5. 一个Job可以绑定多个Trigger
    
  • Calendar

    1
    
    Quartz提供的日历类。一个Trigger可以和多个Calendar关联,以此来排除一些特殊的日期
    

第三节 触发器API的使用

3.1 SimpleTrigger对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public static void main(String[] args) throws SchedulerException {
		
	//1.创建自定义的任务(job)对象
	JobDetail job = JobBuilder.newJob(HelloJob.class).build();
	//2.创建触发器 设置任务启动5秒后开始执行job,一秒执行一次,执行5秒
	Date startDate = new Date();//开始时间
	startDate.setTime(startDate.getTime() + 2000);//设置5秒之后在执行
	Date endDate = new Date();//结束时间
	endDate.setTime(startDate.getTime() + 5000);//结束时间推迟5秒
	/**
	 * withIdentity               : 给任务添加名称和群组方便统一管理,比如可以设置多个触发器名字不同但是群组相同,因为一个任务可以绑定多个触发器
	 *  - name                    : 设置任务名称
	 *  - group                   : 设置群组名称
	 * startNow                   : 立即生效
	 * startAt                    : 触发器开始时间
	 * endAt                      : 触发器结束时间
	 * withSchedule               : 设置规则
	 * withIntervalInMilliseconds : 每隔1000毫秒执行一次Job(HelloJob);还可以使用withIntervalInSeconds方法单位是秒
	 * repeatForever              : 循环执行
	 */
	Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1").
	startNow().
	startAt(startDate).
	endAt(endDate).
	withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(1000).repeatForever()).
	build();
	//3.创建任务调度(Scheduler)对象
	Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
	//4.将任务和触发器联系到一起
	scheduler.scheduleJob(job, trigger);
	//5.启动任务
	scheduler.start();
}

3.2 CronTrigger对象

3.2.1 CronTrigger对象介绍

1
2
3
1. CronTrigger功能非常强大
2. 是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CroTrigger更加常用
3. CroTrigger是基于Cron表达式的

3.2.2 CronTrigger对象使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) throws SchedulerException {
		
	//1.创建自定义的任务(job)对象
	JobDetail job = JobBuilder.newJob(HelloJob.class).build();
	//2.创建触发器,创建一个每天下午16时54分开始执行的触发器
	CronTrigger trigger = TriggerBuilder.newTrigger()
			.withIdentity("job01","group01")
			.startNow()
			.withSchedule(CronScheduleBuilder.cronSchedule("0 54 16 * * ?"))
			.build();
	//3.创建任务调度(Scheduler)对象
	Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
	//4.将任务和触发器联系到一起
	scheduler.scheduleJob(job, trigger);
	//5.启动任务
	scheduler.start();
}

3.2.3 Cron表达式

  • Cron表达式的语法格式
    1
    2
    3
    4
    5
    
    Cron表达式是由7个子表达式组成的字符串,其中"年" 是可选的,可以不指定,格式如下:
    [秒] [分] [小时] [日] [月] [周] [年]
    
    例如1: 
    表达式:  * 30 10 ? * 1/5 *    --> (从后向前解释) --> [指定年份]的[周一到周五][指定月][不指定日][上午10时][30分][指定秒]
    
  • 表达式的每个位置涉及到的符号的取值范围
位置时间域名允许值允许的特殊字符
10-59, - * /
2分钟0-59, - * /
3小时0-23, - * /
4日期1-31, - * ? / L W C
5月份1-12, - * /
6星期1-7, - * ? / L C #
7年(可选)空值1970-2099, - * /

其中特殊字符的含义如下:

符号名称备注
星号(*)可用在所有字段中,表示对应时间域的每一个时刻。例如,*在分钟字段时,表示“每分钟”
问号(?)该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符
减号(-)表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12
逗号(,)表示一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五
斜杠(/)x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y
L该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示一个星期的最后一天(也就是星期六,国外星期第一天为周天)。但是,如果L出现在星期字段里,而且在前面有一个数值X,则表示“这个月的最后一个星期X-1”,例如,6L表示该月的最后一个星期五,5L表示该月的最后一个星期四,以此类推
W该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号是星期二,那结果就是15号星期二。但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天
LW组合在日期字段可以组合使用LW,它的意思是当月的最后一个工作日
井号(#)该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发
C该字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天

  • 常见的Cron表达式(大小写不敏感)
表示式说明
“0 0 12 * * ?”每天12点运行
“0 15 10 ? * *”每天10:15运行
“0 15 10 * * ?”每天10:15运行
“0 15 10 * * ? *”每天10:15运行
“0 15 10 * * ? 2008”在2008年的每天10:15运行
“0 * 14 * * ?”每天14点到15点之间每分钟运行一次,开始于14:00,结束于14:59
“0 0/5 14 * * ?”每天14点到15点每5分钟运行一次,开始于14:00,结束于14:55
“0 0/5 14,18 * * ?”每天14点到15点每5分钟运行一次,此外每天18点到19点每5钟也运行一次
“0 0-5 14 * * ?”每天14:00点到14:05,每分钟运行一次
“0 10,44 14 ? 3 WED”3月每周三的14:10分到14:44,每分钟运行一次
“0 15 10 ? * MON-FRI”每周一,二,三,四,五的10:15分运行
“0 15 10 15 * ?”每月15日10:15分运行
“0 15 10 L * ?”每月最后一天10:15分运行
“0 15 10 ? * 6L”每月最后一个星期五10:15分运行
“0 15 10 ? * 6L 2014-2016”在2014,2015,2016年每个月的最后一个星期五的10:15分运行
“0 15 10 ? * 6#3”每月第三个星期五的10:15分运行
  • 在线生成Cron表达式的工具地址
    1
    2
    
    旧版地址 : https://cron.qqe2.com/
    新版地址 : https://qqe2.com/cron
    

第四节 Spring整合Quartz

Spring整合Quartz依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context-support</artifactId>
	<version>4.3.26.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-tx</artifactId>
	<version>4.3.26.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>>2.2.3</version>
</dependency>

4.1 方式一(JobDetailFactoryBean)

  • 创建任务类(实现Job接口)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    /**
     * 创建自定义任务类
     */
    public class MyJob implements Job{
    
    	public void execute(JobExecutionContext context) throws JobExecutionException {
    		System.out.println("我的任务被执行了..."+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    	}
    }
    
  • 创建Spring配置文件(spring.xml)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    	<!-- 创建任务 -->
    	<bean id="job" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    		<!-- job名称 -->
    		<property name="name" value="job1"></property>
    		<!-- job分组 -->
    		<property name="group" value="group1"></property>
    		<!-- 指定具体的Job类 -->
    		<property name="jobClass" value="com.qianfeng.qs.MyJob"></property>
    	</bean>
    	<!-- 创建触发器 -->
    	<bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    		<!-- 设置触发器名称 -->
    		<property name="name" value="trigger1"></property>
    		<!-- 设置触发器群组 -->
    		<property name="group" value="trigger_group1"></property>
    		<!-- 设置触发的任务 -->
    		<property name="jobDetail" ref="job"></property>
    		<!-- 设置Cron表达式,每隔5s运行一次 -->
    		<property name="cronExpression" value="*/5 * * * * ?"></property>
    	</bean>
    	<!-- 创建任务调度器 -->
    	<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    		<property name="triggers">
    			<list>
    				<ref bean="trigger"/>
    			</list>
    		</property>
    	</bean>
    </beans>
    
  • 测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    public static void main(String[] args) throws SchedulerException, InterruptedException {
        //如果只是启动任务,那么只需要创建IOC容器即可
    	ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
    	// 获取调度器
    	StdScheduler scheduler = (StdScheduler) ioc.getBean("scheduler");
    	// 获取任务
    	JobKey jobKey = JobKey.jobKey("job1", "group1");
    	// 任务的暂停(3秒之后暂停3秒)
    	Thread.sleep(3000);
    	scheduler.pauseJob(jobKey);
    	// 任务的恢复(暂停3秒后恢复)
    	Thread.sleep(3000);
    	scheduler.resumeJob(jobKey);
    	// 任务的删除(3秒之后删除)
    	Thread.sleep(3000);
    	scheduler.deleteJob(jobKey);
    }
    

4.2 方式二(MethodInvokingJobDetailFactoryBean)

  • 创建任务类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    /**
     * 创建自定义任务类
     */
    public class MyJob{
    	/**
    	 * 任务方法1(此方法用于测试SimpleTrigger触发器)
    	 */
    	public void task1() {
    		System.out.println("SimpleTrigger生效了..."+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    	}
    	
    	/**
    	 * 任务方法2(此方法用于测试CronTrigger触发器)
    	 */
    	public void task2() {
    		System.out.println("CronTrigger生效了..."+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    	}
    }
    
  • 创建Spring配置文件(spring.xml)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    	<!-- 将自定义任务类加入到IOC容器中 -->
    	<bean id="myJob" class="com.qianfeng.qs.MyJob"></bean>
    	
    	<!-- 配置固定时长的任务类,并注入被任务调度类和任务方法 -->
    	<bean id="jobDetail1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    		<!-- 注册被调度类 -->
    		<property name="targetObject" ref="myJob"></property>
    		<!-- 注册被调度方法 -->
    		<property name="targetMethod" value="task1"></property>
    		<!-- 设置任务名称 -->
    		<property name="name" value="job1"></property>
    		<!-- 设置任务群组名称 -->
    		<property name="group" value="group1"></property>
    	</bean>
    	
    	<!-- 配置cron表达式的任务类,并注入被任务调度类和任务方法 -->
    	<bean id="jobDetail2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    		<!-- 注册被调度类 -->
    		<property name="targetObject" ref="myJob"></property>
    		<!-- 注册被调度方法 -->
    		<property name="targetMethod" value="task2"></property>
    		<!-- 设置任务名称 -->
    		<property name="name" value="job2"></property>
    		<!-- 设置任务群组名称 -->
    		<property name="group" value="group1"></property>
    	</bean>
    	
    	<!-- 配置固定时长的触发器并配置任务的时间 -->
    	<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
    		<!-- 配置此触发器作用的任务类 -->
    		<property name="jobDetail" ref="jobDetail1"></property>
    		<!-- 指定触发器执行的时间间隔 -->
    		<property name="repeatInterval" value="1000"></property>
    	</bean>
    	
    	<!-- 配置cron表达式的触发器并配置任务的规则 -->
    	<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    		<!-- 配置此触发器作用的任务类 -->
    		<property name="jobDetail" ref="jobDetail2"></property>
    		<!-- 指定触发器执行的时间间隔 -->
    		<property name="cronExpression" value="0/1 * * * * ?"></property>
    	</bean>
    	
    	<!-- 配置调度 -->
    	<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    		<property name="triggers">
    			<list>
    				<ref bean="simpleTrigger"/>
    				<ref bean="cronTrigger"/>
    			</list>
    		</property>
    	</bean>
    	
    </beans>
    
    
  • 测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    public static void main(String[] args) throws InterruptedException, SchedulerException{
    	// 如果只是启动任务,那么只需要创建IOC容器即可
    	ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
    	// 获取调度器
    	StdScheduler scheduler = (StdScheduler) ioc.getBean("scheduler");
    	// 获取某一个组的所有任务
    	GroupMatcher<JobKey> group1 = GroupMatcher.groupEquals("group1");
    	// 3秒之后暂停当前组的所有任务
    	Thread.sleep(3000);
    	scheduler.pauseJobs(group1);
    	// 5秒之后恢复当前组的任务
    	Thread.sleep(5000);
    	scheduler.resumeJobs(group1);
    }
    

第五节 Quartz默认配置文件

  • 简介
    1
    2
    3
    4
    
    设置quartz的初始化配置
    quartz.properties 是Quartz的默认配置,主要使用配置和调度工厂类(StdSchedulerFactory)实例化调度对象(Scheduler)
    默认存在于 quartz依赖的org.quartz.Scheduler路径下,如果想修改默认值可以在当前classpath下创建同名文件修改默认值
    或者直接配置到spring的xml文件中
    
  • xml配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    	<!-- 创建任务 -->
    	<bean id="job" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    		<!-- job名称 -->
    		<property name="name" value="job1"></property>
    		<!-- job分组 -->
    		<property name="group" value="group1"></property>
    		<!-- 指定具体的Job类 -->
    		<property name="jobClass" value="com.qianfeng.qs.MyJob"></property>
    	</bean>
    	<!-- 创建触发器 -->
    	<bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    		<!-- 设置触发器名称 -->
    		<property name="name" value="trigger1"></property>
    		<!-- 设置触发器群组 -->
    		<property name="group" value="trigger_group1"></property>
    		<!-- 设置触发的任务 -->
    		<property name="jobDetail" ref="job"></property>
    		<!-- 设置Cron表达式,每隔5s运行一次 -->
    		<property name="cronExpression" value="*/1 * * * * ?"></property>
    	</bean>
    	<!-- 创建任务调度器 -->
    	<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    		<property name="triggers">
    			<list>
    				<ref bean="trigger"/>
    			</list>
    		</property>
    		<!-- 
    			设置quartz的初始化配置
    			quartz.properties 是Quartz的默认配置,主要使用配置和调度工厂类(StdSchedulerFactory)实例化调度对象(Scheduler)
    			默认存在于 quartz依赖的org.quartz.Scheduler路径下,如果想修改默认值可以在当前classpath下创建同名文件修改默认值
    			或者直接配置到spring的xml文件中
    		 -->
    		<!-- <property name="configLocation" value="classpath:quartz.properties"></property> -->
    		<!-- <property name="quartzProperties">
    			<props>
    				<prop key="org.quartz.scheduler.instanceName">DefaultQuartzScheduler</prop>
    			</props>
    		</property> -->
    	</bean>
    </beans>
    

第六节 Quartz和Spring框架整合解决在任务中不能注入的问题

6.1 Quartz不能注入service或者dao(mapper)层原因

1
这个Job是由quartz实例化出来的,不受Spring的管理,所以就导致注入失败

6.2 解决方案

  • 如何将非Spring的IOC容器创建的bean加入到IOC容器中?
    1
    2
    3
    4
    5
    6
    7
    
    我们的任务是由Spring框架的spring-context-support依赖中SpringBeanJobFactory类的createJobInstance方法创建
    但是只是创建了对象却没有加入到IOC容器中,所以要想将任务加入到IOC容器中首先就是需要继承SpringBeanJobFactory类并重写createJobInstance方法
    将创建的任务对象手动加入到IOC容器中,那么问题来了,我们创建好了任务之后怎么加入到Spring的IOC容器中呢???
    
    ↓↓↓↓↓↓↓↓
    
    AutowireCapableBeanFactory可以实现对已存在实例进行管理,捆绑并填充并不由Spring管理生命周期并已存在的对象.
    
  • 重写用于生成job实例的SpringBeanJobFactory
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    /**
     * 重写SpringBeanJobFactory类,用于生成job实例,并且使用AutowireCapableBeanFactory类
     * 的autowireBean方法将新生成的job实例加入到IOC中
     */
    public class CustomerJobFactory extends SpringBeanJobFactory {
        @Autowired
        private AutowireCapableBeanFactory capableBeanFactory;
        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            //创建job实例
            Object jobInstance = super.createJobInstance(bundle);
            //将job实例通过AutowireCapableBeanFactory的autowireBean方法加入到IOC中进行管理
            capableBeanFactory.autowireBean(jobInstance);
            return jobInstance;
        }
    }
    
  • 将重写了的SpringBeanJobFactory加入到IOC中进行实例化
    1
    2
    
    <!--设置id方便被引用-->
    <bean id="customJobFactory" class="com.qianfeng.task.CustomJobFactory"></bean>
    
  • Quartz在Spring中的配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    <!--将重写了的SpringBeanJobFactory加入到IOC中进行实例化-->
    <bean id="customJobFactory" class="com.qianfeng.task.CustomJobFactory"></bean>
    
    <!--配置quartz-->
    <bean id="job" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <!-- job名称 -->
        <property name="name" value="job1"></property>
        <!-- job分组 -->
        <property name="group" value="group1"></property>
        <!-- 指定具体的Job类 -->
        <property name="jobClass" value="com.qianfeng.job.HelloJob"></property>
    </bean>
    <!-- 创建触发器 -->
    <bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <!-- 设置触发器名称 -->
        <property name="name" value="trigger1"></property>
        <!-- 设置触发器群组 -->
        <property name="group" value="trigger_group1"></property>
        <!-- 设置触发的任务 -->
        <property name="jobDetail" ref="job"></property>
        <!-- 设置Cron表达式,每隔5s运行一次 -->
        <property name="cronExpression" value="*/5 * * * * ?"></property>
    </bean>
    <!-- 创建任务调度器 -->
    <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!--在调度器中重新引入自定义的SpringBeanJobFactory,这时的任务已经被加入到了IOC中-->
        <property name="jobFactory" ref="customJobFactory"></property>
        <property name="triggers">
            <list>
                <ref bean="trigger"/>
            </list>
        </property>
    </bean>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/198005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么要使用采购管理软件 采购管理软件推荐

在企业发展道路上&#xff0c;采购部门是一个非常重要的组织&#xff0c;它会直接影响到企业的经济效益。企业在采购活动中&#xff0c;如果还是采用传统线下的采购方式&#xff0c;那么很容易导致采购信息不集中&#xff0c;效率低&#xff0c;出错率高&#xff0c;最终损害企…

爱情呼叫转移-深度广度遍历合集

1.这件事是特殊的&#xff0c;还是普遍的&#xff1f; 工作中常常会遇到各种各样的问题&#xff0c;不管黑猫白猫&#xff0c;抓到老鼠就是好猫。哪只猫好&#xff0c;往往需要对比分析。 如何做数据对比&#xff0c;需要加入哪些数据来分析&#xff0c;在哪里进行数据对比&am…

查找 二分查找 (终极巩固)

二分条件&#xff1a; 1) 序列有序 2&#xff09;支持随机访问 二分思想&#xff1a; 大体思想是二分之后如果目标值在左侧&#xff0c;则中间包括右边区间所有pass掉 right mid - 1; 目标在右侧&#xff0c;则中间包括左边所有pass left mid 1; 注意点 left < rig…

Python Fiddler抓包工具教学,获取公众号(pc客户端)数据

前言 今天来教大家如何使用Fiddler抓包工具&#xff0c;获取公众号&#xff08;PC客户端&#xff09;的数据。 Fiddler是位于客户端和服务器端的HTTP代理&#xff0c;是目前最常用的http抓包工具之一。 开发环境 python 3.8 运行代码pycharm 2021.2 辅助敲代码requests 第三方…

VS2022 开发Qt之修改软件图标

开发环境本次实验使用的开发环境是win10 64位系统 IDE使用VS2022,Qt版本是Qt5,15.写博客背景最近再练习使用VS开发Qt,到修改软件图标的事情.在网上搜索了一番大部分修改图标的都是基于Qt自带的编译器,由于本人使用的VS的IDE和自带的编译器设置方法有所不同,在一番查找实验后还整…

【论文学习】YOLOv1-YOLOv4

文章目录You Only Look Once,Unified ,Real-Time Object DetectionAbstractIntroductionUnified DetectionNetwork DesignTrainingInferenceLimitations of YOLOComparison to Other Detection SystemsYOLO9000:Better,Faster,StrongerAbstractIntroductionBetterBatch Normali…

【C++之类和对象】日期类的实现

目录前言一、日期类的基本样式二、构造函数三、拷贝构造函数四、赋值运算符重载五、日期比较1. 判断一个日期是否小于另一个日期2. 判断一个日期和另一个日期是否相等3. 判断一个日期是否小于等于另一个日期4. 判断一个日期是否大于另一个日期5. 判断一个日期是否大于等于另一个…

独孤九剑xss通关教程

独孤九剑xss通关教程 独孤九剑第一式&#xff1a; 这里过滤了 () 构造payload&#xff1a; ?data"><svg><script>%26%23x65%3B%26%23x76%3B%26%23x61%3B%26%23x6c%3B%26%23x28%3B%26%23x6c%3B%26%23x6f%3B%26%23x63%3B%26%23x61%3B%26%23x74%3B%26%23…

开门红,农民大衣哥兔年第一条祝福,为何在百万艺人中选择杨语莲

俗话说&#xff1a;人逢喜事精神爽。这句话用到农民歌唱家大衣哥身上&#xff0c;就再贴切不过了&#xff0c;因为在新年即将来临之际&#xff0c;他的儿子小伟又一次结婚了。大衣哥是一个非常接地气的明星&#xff0c;这些年来他无绯闻不炒作&#xff0c;堪称为娱乐圈的楷模&a…

开学季,送初三学生什么礼物最实用?2023学生护眼台灯分享

春节的新学期即将到来&#xff0c;送给初中孩子什么礼物比较好呢&#xff0c;还是要对学习有所帮助的&#xff0c;还需要培养孩子的兴趣&#xff0c;在挑选礼物时&#xff0c;也是斟酌了很久&#xff0c;面对现在很多孩子的有近视问题&#xff0c;在我国的近视人数达到7亿人&am…

java面试题(十一)IO流篇

2.21 请介绍TreeMap的底层原理 参考答案 TreeMap基于红黑树&#xff08;Red-Black tree&#xff09;实现。映射根据其键的自然顺序进行排序&#xff0c;或者根据创建映射时提供的 Comparator 进行排序&#xff0c;具体取决于使用的构造方法。TreeMap的基本操作containsKey、g…

三维重建——商汤NeuralRecon算法详解与论文解读

论文地址:https://arxiv.org/abs/2104.00681 1.三维重建任务概述 三维重建,就是将2D的图片信息重建为3D的信息。应用领域广泛。可以应用于原型设计、虚拟现实等。 2.三维重建基础 (1) 相机成像 相机成像一般是小孔成像的原理,f就是焦距,o就是光圈;右图为光圈大小对清晰…

【多尺度注意力的轻量化图像超分辨率】

MSAR-Net: Multi-scale attention based light-weight image super-resolution &#xff08;MSAR-Net&#xff1a;基于多尺度注意力的轻量化图像超分辨率&#xff09; 近年来&#xff0c;单幅图像超分辨率&#xff08;SISR&#xff09;技术在视频和图像处理领域得到了广泛的应…

Python基础语法预习,开学查漏补缺

嗨害大家好鸭~我是小熊猫 Python3 基础语法 Python学习资料电子书 点击此处跳转文末名片 编码 默认情况下&#xff0c;Python 3 源码文件以 UTF-8 编码&#xff0c; 所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的编码&#xff1a; # -*- coding: cp-125…

(HR职场)什么是计划能力?如何提高计划能力?

不论是学习还是工作&#xff0c;光靠努力是不行的&#xff0c;还得有计划&#xff0c;有周密的部署&#xff0c;懂得按计划做事情的人&#xff0c;不仅可以高效率地完成工作&#xff0c;还能在枯燥的工作中寻找到乐趣。这就是做计划的意义和必要性。当然光有计划也不行&#xf…

ArcGIS基础:将多个面要素融合成一个多边形面要素操作

操作目标&#xff1a;有多个多边形要素&#xff0c;并且字段属性没有统一的&#xff0c;可以采用以下两种办法融合成一个面要素。 如下所示&#xff0c;是对被选中的高亮数据进行处理的。 下面介绍第一种方法&#xff1a; 保持数据选中状态&#xff0c;找到【地理处理】下的…

Codeforces Round #849 (Div. 4) D Distinct Split

题目&#xff1a;大概翻译&#xff1a;让我们把一个字符串x的f(z)函数表示为该字符串包含的不同字符数。例如&#xff0c;f(abc)3。f(bbbb) 1, 和 f(babacaba) 3. 给定一个字符串s&#xff0c;将其分成两个非空字符串a和b&#xff0c;使f(a)f(b)为最大可能。换句话说&#xf…

2023软考软件设计师易混淆知识点~(7)

将2023上半年软考《软件设计师》易混淆知识点&#xff0c;分享给大家&#xff0c;快来跟着一起打卡学习吧&#xff01;--<<<点击链接加入群聊【软考学习交流群】>>>易混淆点 :对称加密和非对称加密1、对称加密技术:KeKd;加密解密共用一个密钥;特点:加密强度不…

python设计模式-适配器设计模式,装饰器设计模式

适配器设计模式 适配器模式可用作两个不兼容接口之间的桥梁。 这种类型的设计模式属于结构模式&#xff0c;因为此模式结合了两个独立接口的功能。 这种模式涉及一个类&#xff0c;它负责连接独立或不兼容接口的功能。 一个现实的例子是读卡器&#xff0c;它是存储卡和笔记本电…

超多免费API接口分享

分享一下近段时间在网上看的超多免费API接口&#xff0c;赶紧收藏起来吧&#xff01; 一、APISpace 为超过100 万开发者提供专业的 API 服务&#xff0c;包括 API 管理、测试、访问控制等功能&#xff0c;让您无忧探索广阔的API世界~所有接口提供免费试用 https://www.apisp…