源码分析Elastic-Job前置篇:Spring自定义命名空间原理

本文涉及的产品
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 在 Spring 中使用 Elastic-Job 的示例如下:

在 Spring 中使用 Elastic-Job 的示例如下:

<!--配置作业注册中心 -->
<reg:zookeeper id="regCenter" server-lists="${gis.dubbo.registry.address}"
      namespace="example-job" base-sleep-time-milliseconds="${elasticJob.zkBaseSleepTimeMilliseconds}"
      max-sleep-time-milliseconds="${elasticJob.zkMaxSleepTimeMilliseconds}"
      max-retries="${elasticJob.zkMaxRetries}" />

本文重点剖析如何在 Spring 中自定义命名空间 < reg:zookeeper/>。

1、在META-INF目录下定义xsd文件,Elastic-Job reg.xsd文件定义如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.dangdang.com/schema/ddframe/reg"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:beans="http://www.springframework.org/schema/beans"
        targetNamespace="http://www.dangdang.com/schema/ddframe/reg"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">
    <xsd:import namespace="http://www.springframework.org/schema/beans"/>
    
    <xsd:element name="zookeeper">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="server-lists" type="xsd:string" use="required" />
                    <xsd:attribute name="namespace" type="xsd:string" use="required" />
                    <xsd:attribute name="base-sleep-time-milliseconds" type="xsd:string" />
                    <xsd:attribute name="max-sleep-time-milliseconds" type="xsd:string" />
                    <xsd:attribute name="max-retries" type="xsd:string" />
                    <xsd:attribute name="session-timeout-milliseconds" type="xsd:string" />
                    <xsd:attribute name="connection-timeout-milliseconds" type="xsd:string" />
                    <xsd:attribute name="digest" type="xsd:string" />
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>
  • xsd:schema元素详解

    • xmlns="http://www.dangdang.com/schema/ddframe/reg":定义默认命名空间。如果元素没有前缀,默认为该命名空间下的元素。
    • xmlns:xsd="http://www.w3.org/2001/XMLSchema",引入xsd命名空间,该命名空间的URL为http://www.w3.org/2001/XMLSchema,元素前缀为xsd。
    • xmlns:beans="http://www.springframework.org/schema/beans",引入Spring beans命名空间.xmlns:xx=""表示引入已存在的命名空间。
    • targetNamespace="http://www.dangdang.com/schema/ddframe/reg":定义该命名空间所对应的url,在xml文件中如果要使用< reg:xx/>,其xsi:schemaLocation定义reg.xsd路径时必须以该值为键,例如应用程序中定义elasticjob的xml文件如下:
    • elementFormDefault="qualified":指定该xsd所对应的实例xml文件,引用该文件中定义的元素必须被命名空间所限定。例如在reg.xsd中定义了zookeeper这个元素,那么在spring-elastic-job.xml(xml文档实例)中使用该元素来定义时,必须这样写: ,而不能写出。
    • attributeFormDefault:指定该xsd所对应的示例xml文件,引用该文件中定义的元素属性是否需要被限定,unqualified表示不需要被限定。如果设置为qualified,则则为错误写法,正确写法如下:

      <reg:zookeeper id="regCenter" reg:server-lists="" .../>。
  • xsd:import
    导入其他命名空间,< xsd:import namespace="http://www.springframework.org/schema/beans"/>

表示导入spirng beans命名空间。如果目标命名空间定义文件没有指定targetNamespace,则需要使用include导入其他命令空间,例如:

<import namespace="tnsB" schemaLocation="B.xsd"> 
  • xsd:zookeeper> 定义zookeeper元素,xml文件中可以使用reg:zookeeper/>。
  • xsd:complexType,zookeeper元素的类型为复杂类型。
  • xsd:extension base="beans:identifiedType">继承beans命名空间identifiedType的属性。(id 定义)。

2、定义NamespaceHandlerSupport实现类。

继承NamespaceHandlerSupport,重写init方法。

public final class RegNamespaceHandler extends NamespaceHandlerSupport {
    
    @Override
    public void init() {
        registerBeanDefinitionParser("zookeeper", new ZookeeperBeanDefinitionParser());
    }
}

注册BeanDefinitionParser解析< reg:zookeeper/>标签,并初始化实例。

ZookeeperBeanDefinitionParser源码:

public final class ZookeeperBeanDefinitionParser extends AbstractBeanDefinitionParser {
    @Override
    protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext parserContext) {
        BeanDefinitionBuilder result = BeanDefinitionBuilder.rootBeanDefinition(ZookeeperRegistryCenter.class);// @1
        result.addConstructorArgValue(buildZookeeperConfigurationBeanDefinition(element));  // @2
        result.setInitMethodName("init");   // @3
        return result.getBeanDefinition();  // @4
    }
 //  ....省略部分代码
}

代码@1:构建器模式,表明< reg:zookeeper/>标签对应的实体Bean对象为 ZookeeperRegistryCenter,zk注册中心实现类。
代码@2:最终创建 ZookeeperRegistryCenter,其属性通过构造方法注入。
代码@3:设置 initMethod,相当于配置文件的 init-method 属性,表明在创建实例时将调用该方法进行初始化。
代码@4:返回 AbstractBeanDefinition 对象,方便 Spring 针对该配置创建实例。

ZookeeperBeanDefinitionParser#buildZookeeperConfigurationBeanDefinition

private AbstractBeanDefinition buildZookeeperConfigurationBeanDefinition(final Element element) {
        BeanDefinitionBuilder configuration = BeanDefinitionBuilder.rootBeanDefinition(ZookeeperConfiguration.class);
        configuration.addConstructorArgValue(element.getAttribute("server-lists"));
        configuration.addConstructorArgValue(element.getAttribute("namespace"));
        addPropertyValueIfNotEmpty("base-sleep-time-milliseconds", "baseSleepTimeMilliseconds", element, configuration);
        addPropertyValueIfNotEmpty("max-sleep-time-milliseconds", "maxSleepTimeMilliseconds", element, configuration);
        addPropertyValueIfNotEmpty("max-retries", "maxRetries", element, configuration);
        addPropertyValueIfNotEmpty("session-timeout-milliseconds", "sessionTimeoutMilliseconds", element, configuration);
        addPropertyValueIfNotEmpty("connection-timeout-milliseconds", "connectionTimeoutMilliseconds", element, configuration);
        addPropertyValueIfNotEmpty("digest", "digest", element, configuration);
        return configuration.getBeanDefinition();
    }

根据< reg:zookeeper/>元素,获取 element 的server-lists、namespace 属性,使用ZookeeperConfiguration 构造方式初始化 ZookeeperConfiguration属性,然后解析其他非空属性并使用set 方法注入到 ZookeeperConfiguration 实例。

3、将自定义的 NameSpace、xsd 文件纳入 Spring 的管理范围内。

在 META-INF 目录下创建 spring.handlers、spring.schemas 文件,其内容分别是:

spring.handlers:http\://www.dangdang.com/schema/ddframe/reg=io.elasticjob.lite.spring.reg.handler.RegNamespaceHandler

格式如下:xsd文件中定义的targetNamespace=自定义namespace实现类。

spring.schemas:http\://www.dangdang.com/schema/ddframe/reg/reg.xsd=META-INF/namespace/reg.xsd

格式如下:xsd文件uri = xsd文件目录。

xsi:schemaLocation="http\://www.dangdang.com/schema/ddframe/reg/reg.xsd=META-INF/namespace/reg.xsd"

取的就是该文件的内容。然后元素解析后,然后实例化Bean并调用ZookeeperRegistryCenter的init方法,开始注册中心的启动流程。

下一篇将详细介绍elastic-job注册中心的启动流程。

原文发布时间为:2019-11-28
本文作者:丁威,《RocketMQ技术内幕》作者。
本文来自中间件兴趣圈,了解相关信息可以关注中间件兴趣圈

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
27天前
|
存储 人工智能 自然语言处理
RAG 调优指南:Spring AI Alibaba 模块化 RAG 原理与使用
通过遵循以上最佳实践,可以构建一个高效、可靠的 RAG 系统,为用户提供准确和专业的回答。这些实践涵盖了从文档处理到系统配置的各个方面,能够帮助开发者构建更好的 RAG 应用。
733 113
|
5月前
|
监控 Java 应用服务中间件
Spring Boot整合Tomcat底层源码分析
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置和起步依赖等特性,大大简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是其与Tomcat的整合。
149 1
|
18天前
|
安全 前端开发 Java
Spring Boot 项目中触发 Circular View Path 错误的原理与解决方案
在Spring Boot开发中,**Circular View Path**错误常因视图解析与Controller路径重名引发。当视图名称(如`login`)与请求路径相同,Spring MVC无法区分,导致无限循环调用。解决方法包括:1) 明确指定视图路径,避免重名;2) 将视图文件移至子目录;3) 确保Spring Security配置与Controller路径一致。通过合理设定视图和路径,可有效避免该问题,确保系统稳定运行。
63 0
|
5月前
|
XML Java 开发者
Spring Boot开箱即用可插拔实现过程演练与原理剖析
【11月更文挑战第20天】Spring Boot是一个基于Spring框架的项目,其设计目的是简化Spring应用的初始搭建以及开发过程。Spring Boot通过提供约定优于配置的理念,减少了大量的XML配置和手动设置,使得开发者能够更专注于业务逻辑的实现。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,为开发者提供一个全面的理解。
84 0
|
1月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——拦截自定义异常
本文介绍了在实际项目中如何拦截自定义异常。首先,通过定义异常信息枚举类 `BusinessMsgEnum`,统一管理业务异常的代码和消息。接着,创建自定义业务异常类 `BusinessErrorException`,并在其构造方法中传入枚举类以实现异常信息的封装。最后,利用 `GlobalExceptionHandler` 拦截并处理自定义异常,返回标准的 JSON 响应格式。文章还提供了示例代码和测试方法,展示了全局异常处理在 Spring Boot 项目中的应用价值。
49 0
|
3月前
|
监控 Java 应用服务中间件
SpringBoot是如何简化Spring开发的,以及SpringBoot的特性以及源码分析
Spring Boot 通过简化配置、自动配置和嵌入式服务器等特性,大大简化了 Spring 应用的开发过程。它通过提供一系列 `starter` 依赖和开箱即用的默认配置,使开发者能够更专注于业务逻辑而非繁琐的配置。Spring Boot 的自动配置机制和强大的 Actuator 功能进一步提升了开发效率和应用的可维护性。通过对其源码的分析,可以更深入地理解其内部工作机制,从而更好地利用其特性进行开发。
93 6
|
4月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
4月前
|
XML Java 数据格式
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
本文介绍了在使用Spring框架时,如何通过创建`applicationContext.xml`配置文件来管理对象。首先,在resources目录下新建XML配置文件,并通过IDEA自动生成部分配置。为完善配置,特别是添加AOP支持,可以通过IDEA的Live Templates功能自定义XML模板。具体步骤包括:连续按两次Shift搜索Live Templates,配置模板内容,输入特定前缀(如spring)并按Tab键即可快速生成完整的Spring配置文件。这样可以大大提高开发效率,减少重复工作。
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
|
4月前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
357 14
|
5月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
下一篇
oss创建bucket