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)
具体NamespaceHandler
该NamespaceHandler负责注册一个ConfigPropertySourcesProcessor实例,并且设置apollo.namespace+order
ConfigPropertySourcesProcessor类继承了PropertySourcesProcessor,并注册了其他相关类
PropertySourcesProcessor类为Apollo与Spring结合的关键类,PropertySourcesProcessor主要功能如下:
1.修改ConfigurableEnvironment,添加Apollo配置源(initializePropertySources());
2.设置监听器,动态修改(反射)属性值(initializeAutoUpdatePropertiesFeature(beanFactory))
SpringBoot集成方式:
方式1:通过注解@EnableApolloConfig
查看@EnableApolloConfig定义,发现该注解上包括@Import注解,通过@Import导入对象ApolloConfigRegistrar
ApolloConfigRegistrar定义如下,与ConfigPropertySourcesProcessor实现类似,首先设置了apollo.namespace+order,然后注册了一个PropertySourcesProcessor及其他相关实例,由PropertySourcesProcessor负责初始化apollo配置源并监听配置变化(参考上文PropertySourcesProcessor说明)
方式2:spring.factories扩展机制(Spring中的Java SPI机制升级)
在apollo.jar包中META-INF/spring.factories已默认配置扩展初始化器
结合注解@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注解方式)
同理在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源码,可以总结出插件实现方式如下:
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);