XXL-Job详解(四):任务注册原理

目录

    • 前言
    • 任务注册
    • 注册方法

前言

看该文章之前,最好看一下之前的文章,比较方便我们理解
XXL-Job详解(一):组件架构
XXL-Job详解(二):安装部署
XXL-Job详解(三):任务开发

任务注册

我们在执行器开发任务的时候,只需要一个@XxlJob注解就可以定义一个任务,那么它是怎么做到的呢

xxl-job之前的版本中是通过继承 IJobHandler 和在类上加注解的方式进行任务标识,在最新版中则抛弃了原有的做法,将任务的粒度细化到了方法级别。

前者的好处是任务编写的范式已经规定好,只需要重写对应抽象类中的方法并加上注解,但每一次编写新的任务执行程序都需要创建新的类来重新实现接口。后者的好处是在于细化了任务的粒度,将注解细化到了方法级别,不需要再重复地继承方法,很好地实现了类的复用。

在SpringBoot版本中,我们使用的执行器是XxlJobSpringExecutor,它是XxlJobExecutor的子类,并且实现了ApplicationContextAware 、SmartInitializingSingleton、DisposableBean 三个接口

public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware, SmartInitializingSingleton, DisposableBean {
}

下面介绍一下XxlJobSpringExecutor实现的三个接口

ApplicationContextAware
ApplicationContextAware 是 Spring 框架中的一个接口,用于在 Spring 容器中获取 ApplicationContext 对象。通过实现这个接口,可以将 Spring 容器中的上下文信息注入到 JavaBean 中,从而让 JavaBean 访问 Spring 配置文件中的 Bean 和其他资源。

当一个类实现 ApplicationContextAware 接口时,Spring 容器会自动将当前应用程序的 ApplicationContext 对象注入到该类的 setApplicationContext 方法中。这样,该类就可以通过 ApplicationContext 对象访问 Spring 容器中的其他 Bean 和资源。

SmartInitializingSingleton
SmartInitializingSingleton 是 Spring 框架中的一个接口,它用于定义在单例对象初始化时执行特定操作的接口。主要用于在Spring容器启动完成时进行扩展操作,即afterSingletonsInstantiated()方法;

DisposableBean
DisposableBean,是在Spring容器关闭的时候预留的一个扩展点,实现DisposableBean接口,并重写destroy(),可以在Spring容器销毁bean的时候获得一次回调

注册方法

下面是XxlJobSpringExecutor实现SmartInitializingSingleton接口的afterSingletonsInstantiated方法,任务注册就在这个方法里

	@Overridepublic void afterSingletonsInstantiated() {// init JobHandler Repository/*initJobHandlerRepository(applicationContext);*/// init JobHandler Repository (for method)initJobHandlerMethodRepository(applicationContext);// refresh GlueFactoryGlueFactory.refreshInstance(1);// super starttry {super.start();} catch (Exception e) {throw new RuntimeException(e);}}

可以看到在 afterSingletonsInstantiated 方法做了这样几件事情:

1、初始化任务执行程序仓库,即进行任务注册
2、刷新GlueFactory,获取SpringGlueFactory(用于动态脚本任务)
3、启动执行器,此处调用父类start()方法

可以看到任务注册的方法就在initJobHandlerMethodRepository方法

private void initJobHandlerMethodRepository(ApplicationContext applicationContext) {if (applicationContext == null) {return;}// 获取bean名称列表String[] beanDefinitionNames = applicationContext.getBeanNamesForType(Object.class, false, true);for (String beanDefinitionName : beanDefinitionNames) {// 从上下文中根据bean元数据名称获取bean对象Object bean = applicationContext.getBean(beanDefinitionName);Map<Method, XxlJob> annotatedMethods = null;   // referred to :org.springframework.context.event.EventListenerMethodProcessor.processBeantry {
// 根据bean类元信息获取被@XxlJob注解的方法annotatedMethods = MethodIntrospector.selectMethods(bean.getClass(),new MethodIntrospector.MetadataLookup<XxlJob>() {@Overridepublic XxlJob inspect(Method method) {return AnnotatedElementUtils.findMergedAnnotation(method, XxlJob.class);}});} catch (Throwable ex) {logger.error("xxl-job method-jobhandler resolve error for bean[" + beanDefinitionName + "].", ex);}//如果没有xxljob方法,则跳过if (annotatedMethods==null || annotatedMethods.isEmpty()) {continue;}for (Map.Entry<Method, XxlJob> methodXxlJobEntry : annotatedMethods.entrySet()) {//获取被注解的方法Method executeMethod = methodXxlJobEntry.getKey();//获取注解信息XxlJob xxlJob = methodXxlJobEntry.getValue();// 注册handlerregistJobHandler(xxlJob, bean, executeMethod);}}}protected void registJobHandler(XxlJob xxlJob, Object bean, Method executeMethod){if (xxlJob == null) {return;}//获取任务名称String name = xxlJob.value();//make and simplify the variables since they'll be called several times laterClass<?> clazz = bean.getClass();String methodName = executeMethod.getName();//判断任务名称是否有效if (name.trim().length() == 0) {throw new RuntimeException("xxl-job method-jobhandler name invalid, for[" + clazz + "#" + methodName + "] .");}//检查当前任务名是否已经被使用,注意这里是通过任务名称来进行任务判重的if (loadJobHandler(name) != null) {throw new RuntimeException("xxl-job jobhandler[" + name + "] naming conflicts.");}executeMethod.setAccessible(true);// 设置初始化方法和销毁方法Method initMethod = null;Method destroyMethod = null;if (xxlJob.init().trim().length() > 0) {try {initMethod = clazz.getDeclaredMethod(xxlJob.init());initMethod.setAccessible(true);} catch (NoSuchMethodException e) {throw new RuntimeException("xxl-job method-jobhandler initMethod invalid, for[" + clazz + "#" + methodName + "] .");}}if (xxlJob.destroy().trim().length() > 0) {try {destroyMethod = clazz.getDeclaredMethod(xxlJob.destroy());destroyMethod.setAccessible(true);} catch (NoSuchMethodException e) {throw new RuntimeException("xxl-job method-jobhandler destroyMethod invalid, for[" + clazz + "#" + methodName + "] .");}}//进行任务处理程序注册registJobHandler(name, new MethodJobHandler(bean, executeMethod, initMethod, destroyMethod));}

首先initJobHandlerMethodRepository方法的applicationContext参数就是通过ApplicationContextAware 获取的,下面我们来看下initJobHandlerMethodRepository方法的具体逻辑

1、从ApplicationContext中获取所有Bean元数据名称,通过Bean元数据名称获取所有Bean;
2、遍历获取到的Bean,找到有XxlJob注解的类,获取类中被注解的所有方法;
3、获取被注解方法的相应信息,根据注解中的任务名称,调用loadJobHandler(name)方法检查该任务是否已经注册;
4、进行方法编写范式检查,主要检查方法名称、入参类型以及返回值类型是否符合要求;
5、设置被注解方法的初始化方法和销毁方法;
6、最后,将上述被注解方法注册到任务处理程序仓库中;

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

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

相关文章

万界星空科技MES生产管理系统的主要功能

万界星空科技MES/云MES生产管理系统主要包括以下功能模块&#xff1a; 生产计划管理&#xff1a;根据订单和生产计划&#xff0c;制定详细的调度表和车间生产经营计划&#xff0c;将生产计划和客户订单转化为具体的生产经营计划&#xff0c;消除有效的日常运营&#xff0c;大大…

知识图谱最简单的demo实现

一、简介 知识图谱整个建立过程可以分为以下几点&#xff1a; #mermaid-svg-zJuLB8k8EgBQF8M0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-zJuLB8k8EgBQF8M0 .error-icon{fill:#552222;}#mermaid-svg-zJuLB8k8E…

【C++干货铺】继承 | 多继承 | 虚继承

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 继承的概念及定义 继承的概念 继承的定义 继承基类成员访问方式的变化 基类和派生类的赋值转化 继承中的作用域 派生类的默认成员函数 构造函数 拷贝构造…

基于Java SSM框架+Vue实现大学生兼职信息网站项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架Vue实现大学生兼职信息网站演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认…

nodejs的安装和验证

1.浏览器访问nodejs官网&#xff0c;根据操作系统选择对应版本的安装文件&#xff0c;如下图所示&#xff1a; 2.双击下载的安装文件&#xff0c;点击“Next”&#xff0c;如下图所示&#xff1a; 3.勾选“I accept the terms in the License Agreement”&#xff0c;然后点击“…

MIAOYUN荣获“2023中国赛宝信息技术应用创新优秀解决方案应用创新示范方向三等奖”

11月30日&#xff0c;2023&#xff08;第四届&#xff09;数字化转型推动高质量发展大会在中国海口成功召开&#xff0c;会上举办了2023中国赛宝信息技术应用创新优秀解决方案征集活动颁奖仪式。成都元来云志科技有限公司&#xff08;简称“MIAOYUN”&#xff09;联合国网浙江省…

应用于智慧工厂的AI边缘计算盒子+AI算法软硬一体化方案

智慧工厂解决方案&#xff0c;传统工厂/生产管理&#xff0c;普遍存在运营粗放、效率低、应变能力差、安全隐患突出、资源不平衡等“行业症状”&#xff1b; 以英码产品为核心的智能化场景解决方案&#xff0c;可以从本质上根治这些“症状”&#xff0c;如企业可利用智能预测系…

10.30 作业 C++

设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 #include <iostream>using namespace std;clas…

从零开始Inline Hook

中断表进入0环 通过中断门进入0环&#xff0c;首先了解一下中断门的构成 构造一个中断号 Base:函数地址 DPL:3 //因为三环使用调用门的条件就是CPL(即cs段选择子的RPL)<DPL P:1 //P为1时&#xff0c;中断表才有效 Segment Selector: 0x0008 //中断成功后切换自己的CPL 在…

拥抱复杂性:大模型的发展与挑战

原创 | 文 BFT机器人 大模型代表着机器学习和人工智能领域的前沿技术&#xff0c;它们的发展和应用对于推动科技进步和解决复杂问题具有重要意义。 01 什么是大模型&#xff1f; 大模型是指在计算机科学和人工智能领域中&#xff0c;具有庞大规模和复杂性的模型。这些模型通常…

B/S(Browser/Server)和C/S(Client/Server)

B/S&#xff08;Browser/Server&#xff09;和C/S&#xff08;Client/Server&#xff09;是两种常见的软件架构模式&#xff0c;用于描述客户端与服务器之间的交互方式。 B/S&#xff08;Browser/Server&#xff09;架构&#xff1a; B/S架构是一种基于浏览器和服务器的软件架构…

NOIP2006提高组第二轮T2:金明的预算方案

题目链接 [NOIP2006 提高组] 金明的预算方案 题目描述 金明今天很开心&#xff0c;家里购置的新房就要领钥匙了&#xff0c;新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是&#xff0c;妈妈昨天对他说&#xff1a;“你的房间需要购买哪些物品&#xff0c;怎么布置…

STM32---时钟树

写在前面&#xff1a;一个 MCU 越复杂&#xff0c;时钟系统也会相应地变得复杂&#xff0c;如 STM32F1 的时钟系统比较复杂&#xff0c;不像简单的 51 单片机一个系统时钟就 可以解决一切。对于 STM32F1 系列的芯片&#xff0c;其有多个时钟源&#xff0c;构成了一个庞大的是时…

Verilog 入门(二)(Verilog 语言要素)

文章目录 标识符注释格式系统任务和函数值集合数据类型参数 标识符 Verilog HDL 中的标识符&#xff08;identifier &#xff09;可以是任意一组字母、数字、$ 符号和 _&#xff08;下划线&#xff09;符号的组合&#xff0c;但标识符的第一个字符必须是字母或者下划线。另外&…

docker-compose部署zabbix+grafana

1.引言 1.1目的 zabbixgrafana实现图形化监控 2.部署环境 服务器ip服务版本192.168.5.137zabbix-server6.0.21192.168.5.137grafana10.2.2192.168.5.152zabbix-client6.0.21 3.部署zabbix-server 3.1 创建zabbix目录 mkdir zabbix3.2 编写docker-compose文件 cd zabbix…

【Linux】快速上手自动化构建工具make/makefile

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.什么是make / makefile 2…

class-dump 混淆加固、保护与优化原理

​ 进行逆向时&#xff0c;经常需要dump可执行文件的头文件&#xff0c;用以确定类信息和方法信息&#xff0c;为hook相关方法提供更加详细的数据.class-dump的主要用于检查存储在Mach O文件的Objective-C中的运行时信息&#xff0c;为类&#xff0c;类别和协议生成声明信息&am…

leetcode-142-环形链表(C语言实现)

题目&#xff1a; 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评…

2023年中外Top10快公司研究报告

引言 在市场竞争激烈的环境中&#xff0c;每年都有企业实现显著的高速增长&#xff0c;其利润增长率和销售增长率等关键财务指标在短期内急剧上升。本研究报告精选了一批在2015年至2022年间&#xff0c;其营业收入或营业利润年增长率超过10,000%的企业进行深入分析。这一现象反…

k8s patch 和update区别

在kubernetes中&#xff0c;对资源进行更新的方式有两种一种是update操作&#xff0c;一种是patch操作。对于update请求,我们需要将整个修改后的对象提交给k8s, 而对于patch请求&#xff0c; 我们只需要将对象中某些字段的修改提交给k8s。 kubernetes update跟patch区别 | 好记…