Apollo与Spring集成 - 源码分析

时间:2024-03-31 08:10:26

Spring XML方式:

通过Namespace集成:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:apollo="http://www.ctrip.com/schema/apollo"
       xsi:schemaLocation="http://www.ctrip.com/schema/apollo
                           http://www.ctrip.com/schema/apollo.xsd">
                           
    <apollo:config namespaces="application" order="1"/>
    ...

</beans>

Apollo自定义Spring Namespace(META-INF/apollo-1.0.0.xsd + Spring.handlers + Spring.schemas)

Apollo与Spring集成 - 源码分析

具体NamespaceHandler

Apollo与Spring集成 - 源码分析

该NamespaceHandler负责注册一个ConfigPropertySourcesProcessor实例,并且设置apollo.namespace+order

Apollo与Spring集成 - 源码分析

ConfigPropertySourcesProcessor类继承了PropertySourcesProcessor,并注册了其他相关类

Apollo与Spring集成 - 源码分析

PropertySourcesProcessor类为Apollo与Spring结合的关键类,PropertySourcesProcessor主要功能如下:

1.修改ConfigurableEnvironment,添加Apollo配置源(initializePropertySources());
2.设置监听器,动态修改(反射)属性值(initializeAutoUpdatePropertiesFeature(beanFactory))

Apollo与Spring集成 - 源码分析

 

SpringBoot集成方式:

方式1:通过注解@EnableApolloConfig

Apollo与Spring集成 - 源码分析

查看@EnableApolloConfig定义,发现该注解上包括@Import注解,通过@Import导入对象ApolloConfigRegistrar

Apollo与Spring集成 - 源码分析

ApolloConfigRegistrar定义如下,与ConfigPropertySourcesProcessor实现类似,首先设置了apollo.namespace+order,然后注册了一个PropertySourcesProcessor及其他相关实例,由PropertySourcesProcessor负责初始化apollo配置源并监听配置变化(参考上文PropertySourcesProcessor说明)

Apollo与Spring集成 - 源码分析

方式2:spring.factories扩展机制(Spring中的Java SPI机制升级)

在apollo.jar包中META-INF/spring.factories已默认配置扩展初始化器

Apollo与Spring集成 - 源码分析

结合注解@SpringBootApplication

-> @EnableAutoConfiguration -> @Import(AutoConfigurationImportSelector.class)
-> 加载resources/META_INF/spring.factories中org.springframework.boot.autoconfigure.EnableAutoConfiguration=XX(列表),
此处对应于Apollo配置com.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration,生成@Configuration ApolloAutoConfiguration配置实例,该配置注册了一个ConfigPropertySourcesProcessor实例
-> @Bean ConfigPropertySourcesProcessor extends PropertySourcesProcessor(参照上文ConfigPropertySourcesProcessor说明,我在测试时候将springboot配置文件完全托管在apollo上,本地没有配置文件,也就没有apollo.bootstrap.enabled属性,故该配置实际上并没有生效而是实际生效的是@EnableApolloConfig注解方式)

 Apollo与Spring集成 - 源码分析


同理在resources/META_INF/spring.factories中org.springframework.context.ApplicationContextInitializer=com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer
org.springframework.boot.env.EnvironmentPostProcessor=com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer

中定义了ApolloApplicationContextInitializer扩展,
-> 实际的初始化方法initialize(configurableEnvironment)(此处没有注册changeListener); 
【1】EnvironmentPostProcessor.postProcessEnvironment (执行条件apollo.bootstrap.eagerLoad.enabled=true && apollo.bootstrap.enabled=true)
【2】ApplicationContextInitializer.initialize (执行条件apollo.bootstrap.enabled=true)

(我在本地测试的时候上述2个方法都被调用了,上面的【1】【2】序号即为实际调用顺序,但是由于我把springboot配置文件完全托管在apollo上,本地没有配置文件,也就没有apollo.boostrap.eagerload.enabled和apollo.bootstrap.enabled属性,故initialize方法并没有被执行,该配置实际上并没有生效而实际生效的是@EnableApolloConfig注解方式)

Apollo与Spring集成 - 源码分析

总结:

通过学习Apollo源码,可以总结出插件实现方式如下:
1.Spring.xml命名空间自定义(META-INF/(apollo-1.0.0.xsd + Spring.handlers + Spring.schemas) + NamespaceHandler);
2.SpringBoot启动注解自定义(@EnableApolloConfig + @Import(Class|ImportSelector|ImportBeanDefinitionRegistrar));
3.Spring.factories机制(META-INF/Spring.factories + @EnableAutoConfiguration导入配置 + SpringFactoriesLoader);
4.Java SPI(META-INF/services/接口名(内容:具体接口实现类) + ServiceLoader);