Apollo 1 融合 Spring 的三个入口

时间:2022-09-22 21:31:26

前言

Spring 作为 Java 世界非官方标准框架,任何一个中间件想要得到良好的发展,必须完美支持 Spring 的各种特性,即:无缝融入 Spring。

Apollo 作为分布式配置中心,服务于 Java 应用程序,Java 应用程序可以通过 Apollo 提供的 Client 获取远程配置信息。而如何将这个 Client 高度融合到用户的应用程序中呢?

这就需要针对 Spring 提供给我们的接口进行扩展。

在之前的文章中,已经大致聊过 Spring 的一些扩展接口:深入理解Spring 之 Spring 进阶开发必知必会 之 Spring 扩展接口

而想融入 Spring,首先得找到入口,然后才能注册相关的类进行自己系统的初始化。

所以,如何找到并处理入口成了一门学问,我们今天看看 apollo 如何处理的。

第一种入口:XML

XML 是传统 Java 项目的配置文件,特别是 Spring MVC 项目。虽然现在都是使用的自动化配置,但仍然有一些遗留项目使用 XML,因此,支持 XML 是大部分中间件的必须工作。

支持 XML 需要准守 Spring 的几个约定:

  1. 继承 NamespaceHandlerSupport 抽象类,重写 init 方法,调用 registerBeanDefinitionParser 方法,并传入自己继承的 AbstractSingleBeanDefinitionParser 子类用于解析标签,重写他的 getBeanClass 方法,返回一个 Bean,用于注册相关的 Bean。
  2. classpath 下创建 META-INF 目录,创建 spring.handlers 文件,将 xml 配置中的 URL 指向 NamespaceHandlerSupport
  3. META-INF 目录下,创建 apollo-1.0.0.xsd xsd 文件,用于解释自定义标签。
  4. META-INF 目录下,继续创建 spring.schemas 文件,将 xml 配置中的 xsd URL 指向 xsd 文件。

如果你的 xml 配置中,引用了 apollo 的标签,Spring 将会根据 xml 中的 URL 找到 spring.handlers 中的 NamespaceHandlerSupport 类,并对标签进行解析。也会从 getBeanClass 得到一个设置的 bean,在这个 bean 里,做了 apollo 关键类的注册。

第二种入口:@Import 注解

相对于基于XML的配置,基于Java的配置是目前比较流行的方式。

@Import 注解的使用方式:

  1. 定义一个自己的启动注解。并标注 @import 注解, 其实就是 xml 中的 import 标签,在该注解中,可以配置一个类,这个类就会注册进 Spring 的容器,成为 Bean,你就可以在这个 bean 里做文章。

    在 apollo 中,使用方式如下:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented
@Import(ApolloConfigRegistrar.class)
public @interface EnableApolloConfig {
String[] value() default {ConfigConsts.NAMESPACE_APPLICATION};
int order() default Ordered.LOWEST_PRECEDENCE;
}
  1. 从上面可以看出 ApolloConfigRegistrar 类是 apollo 注册进的 bean。这个 bean 用于处理 @EnableApolloConfig 注解,同时注册 apollo 关键 Bean 到 Spring 容器中。

  2. 用户只需在 Spring 系统中的某个类上,标注 @EnableApolloConfig ,就可以通过 Spring 的方式(自动更新,注解等)使用 apollo 功能。

第三种入口:SpringBoot Starter

目前最流行的框架就是 Spring Boot ,兼容 SpringBoot 是一个大趋势。

Spring Boot 提供 spring-boot-autoconfigure 让第三方框架兼容 Boot,称之为 starter。

创建一个 starter 需要遵守几个约定:

  1. maven 引入 spring-boot-autoconfigure artifact.
  2. 创建一个类,实现ApplicationContextInitializer 接口,重写 initialize 方法,该方法在容器初始化的时候调用。
  3. META-INF 创建 spring.factories 文件,Boot 启动时会自动扫描这个文件。需要在这个文件中写入一个步骤 2 创建的类,类似 org.springframework.context.ApplicationContextInitializer=\com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer。这个类的作用是提前(容器初始化前)加载关键配置到 Spring 环境。
  4. spring.factories 文件中,还需要让 boot 的 EnableAutoConfiguration 自动配置类指向一个自定义类。这是 SpringBoot starter 的关键,例如:org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration。ApolloAutoConfiguration 就会加入的 apollo 的配置 bean 中。你可以在这个配置 bean 中,创建一个关键 bean ,用于处理系统相关的初始化类。例如 apollo 的方式:
@Configuration
@ConditionalOnProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED)
@ConditionalOnMissingBean(PropertySourcesProcessor.class)// 当Spring Context中不存在该Bean时
public class ApolloAutoConfiguration {
@Bean
public ConfigPropertySourcesProcessor configPropertySourcesProcessor() {
return new ConfigPropertySourcesProcessor();
}
}

在 apollo 中,ConfigPropertySourcesProcessor 就是用来注册系统关键 bean 的。

总结

本文重点介绍了 3 种入口:

  1. XML 方式,通过在 getBeanClass 方法返回系统关键 Bean。
  2. @Import 注解,通过在注解中定义 Bean,然后在该 Bean 中处理。
  3. SpringBoot Starter 方式,通过 spring.factories 文件中定义自动配置类,可以注册系统关键 bean。

在以后的开发中,如果想融入 Spring,就可以通过这 3 种方式自行处理。

Apollo 1 融合 Spring 的三个入口的更多相关文章

  1. SpringBoot入门(三)——入口类解析

    本文来自网易云社区 上一篇介绍了起步依赖,这篇我们先来看下SpringBoot项目是如何启动的. 入口类 再次观察工程的Maven配置文件,可以看到工程的默认打包方式是jar格式的. <pack ...

  2. Spring的三种通过XML实现DataSource注入方式

    Spring的三种通过XML实现DataSource注入方式: 1.使用Spring自带的DriverManagerDataSource 2.使用DBCP连接池 3.使用Tomcat提供的JNDI

  3. spring ioc三种注入方式

    spring ioc三种注入方式 IOC ,全称 (Inverse Of Control) ,中文意思为:控制反转 什么是控制反转? 控制反转是一种将组件依赖关系的创建和管理置于程序外部的技术. 由容 ...

  4. Redis实战之征服 Redis &plus; Jedis &plus; Spring (三)

    一开始以为Spring下操作哈希表,列表,真就是那么土.恍惚间发现“stringRedisTemplate.opsForList()”的强大,抓紧时间恶补下. 通过spring-data-redis完 ...

  5. 征服 Redis &plus; Jedis &plus; Spring (三)—— 列表操作【转】

    一开始以为Spring下操作哈希表,列表,真就是那么土.恍惚间发现“stringRedisTemplate.opsForList()”的强大,抓紧时间恶补下. 相关链接: 征服 Redis 征服 Re ...

  6. Spring第三天

    Spring第三天 整体课程安排(3天+2天): 第一天:Spring框架入门.IoC控制反转的配置管理.Spring Web集成.Spring Junit集成. 第二天:Spring AOP面向切面 ...

  7. Spring中三种配置Bean的方式

    Spring中三种配置Bean的方式分别是: 基于XML的配置方式 基于注解的配置方式 基于Java类的配置方式 一.基于XML的配置 这个很简单,所以如何使用就略掉. 二.基于注解的配置 Sprin ...

  8. Spring中三个重要概念 IOC AOP Bean

    Spring中三个重要概念 IOC AOP Bean 首先讲解一下Spring框架,以及为什么要使用Spring 框架? spring 是一个很好的容器框架, 是轻量级的IoC和AOP的容器框架,主要 ...

  9. 相机IMU融合四部曲(三)&colon;MSF详细解读与使用

    相机IMU融合四部曲(三):MSF详细解读与使用 *巧克力 前言 通过前两篇文章,<D-LG-EKF详细解读>和<误差状态四元数详细解读>,已经把相机和IMU融合的理论全部都 ...

随机推荐

  1. java基础-多线程执行

    package Thanqi; public class TestApple implements Runnable{ //苹果的数量 private int count = 5; //拿苹果 //s ...

  2. iOS阶段学习第21天笔记&lpar;ARC内存管理-Copy-代理&rpar;

    iOS学习(OC语言)知识点整理 一.OC 中的ARC内存管理 1)ARC中释放对象的内存原则:看这个对象有没有强引用指向它 2)strong:强引用,默认情况下的引用都是强引用 3) weak:弱引 ...

  3. 常用UML模型简要小结

    关系: 关联(组合,生命周期相同:聚合,物以类聚),依赖,泛化(继承),实现 还有 包含,细化复用已有用例:扩展,非必要主要的用例 图: 1.用例图:就是描述一个功能场景(集合),其实用例编写(前后置 ...

  4. 终端I&sol;O之非规范模式

    关闭termios结构中c_lflag字段的ICANON标志就使终端处于非规范模式.在非规范模式中,输入数据并不组成行,不处理下列特殊字符:ERASE/KILL/EOF/NL/EOL/EOL2/CR/ ...

  5. 我的ECshop二次开发从零开始

    我是一个EC新手,EC就算做再多的模板,肯定也满足不了我们的需要,更何况各行有各行的门道,EC统一做出来的模板也不一定合适于我们这个行业用,因此,只有我们真正掌握了自己做模板,修改模板的功夫,才能真正 ...

  6. 依赖注入与Unity&lpar;一&rpar; 介绍

        在你学习依赖注入和Unity之前,你需要明白你为什么要使用它们.为了明白为什么要使用它们,你应该明白依赖注入和Unity能够帮助你解决什么类型的问题.作为介绍部分,这一章不会涉及太多关于Uni ...

  7. PHP迭代器

    在所有语言中,所有迭代器都必须具有如下4想功能: 1.回滚迭代器到第一个元素 2.潜行到下一个元素 3.获取当前元素 4.验证是否到最后一个元素了 在PHP中我我们可以通过实现iterator来实现迭 ...

  8. 提前防止Non-PIE错误,检测app是否包含PIE标志

    //Howard 2013-07-19 //如何检测app是否包含PIE标志? 答:使用xCode自带的otool工具. otool程序在Xcode.app/Contents/Developer/us ...

  9. 正则表达式 Pattern &amp&semi; Matcher

    1 compile and pattern Pattern类用于创建一个正则表达式,也可以说创建一个匹配模式,它的构造方法是私有的,不可以直接创建,但可以通过Pattern.complie(Strin ...

  10. Flask-在Flask中跨请求传递数据资源

    利用 Flask的底层Werkzeug是有缓存支持的,不用使用redis等第三方. 原文地址如下: https://blog.csdn.net/yannanxiu/article/details/52 ...