Spring和Apollo源码涉及的类
Spring:ApplicationContextInitializer、BeanFactoryPostProcessor、BeanPostProcessor、Environment、CompositePropertySource
Apollo:ApolloApplicationContextInitializer、PropertySourcesProcessor、ApolloProcessor、AutoUpdateConfigChangeListener、SpringValue
Environment和CompositePropertySource
这是Spring的Api,用来存储环境变量。Apollo通过CompositePropertySource向Environment注册了两个PropertySource,命名分别为:ApolloBootstrapPropertySources、ApolloPropertySources。
通过ConfigurableEnvironment#getPropertySources可以获取到Spring所有的属性配置。
ApolloApplicationContextInitializer和ApplicationContextInitializer
ApolloApplicationContextInitializer实现了ApplicationContextInitializer , EnvironmentPostProcessor, Ordered,通过spring.factories使其生效,优先级特别高。这个类在启动时向Environment注册CompositePropertySource,命名为ApolloBootstrapPropertySources,然后遍历命名空间,通过Apollo的ConfigPropertySourceFactory创建命名空间对应的ConfigPropertySource,添加到ApolloBootstrapPropertySources。这样Apollo和Spring共用了同一个对象,Apollo修改配置属性,Environment中的同时会修改,因为是同一个引用!
@EnableApolloConfig和DefaultApolloConfigRegistrarHelper
@EnableApolloConfig是自动配置的入口,通过DefaultApolloConfigRegistrarHelper把命名空间添加到PropertySourcesProcessor的NAMESPACE_NAMES属性中(下面说明);同时DefaultApolloConfigRegistrarHelper会初始化Apollo相关的bean放到Spring IoC。
PropertySourcesProcessor和BeanFactoryPostProcessor
PropertySourcesProcessor实现了BeanFactoryPostProcessor,向Environment注册CompositePropertySource,命名为ApolloPropertySources,遍历@EnableApolloConfig指定的命名空间,通过ConfigPropertySourceFactory获取对应命名空间的属性配置,添加到ApolloPropertySources,然后调整ApolloBootstrapPropertySources和ApolloPropertySources的顺序。同时初始化AutoUpdateConfigChangeListener ,用于实时监听配置的变更。
@Value如何动态修改?
ApolloProcessor、BeanPostProcessor、SpringValue
ApolloProcessor实现了BeanPostProcessor,在Spring bean初始化过程中,每个bean都会执行特定的动作。ApolloProcessor有如下三个子类,所有bean的初始化阶段都会执行。
- ApolloAnnotationProcessor:筛选bean所有Fields和Methods,判断是否存在ApolloConfig和ApolloConfigChangeListener注解
- SpringValueProcessor:判断bean的Fields和Methods是否存在@Value,把bean和@Value封装SpringValue,由SpringValueRegistry存储
- ApolloJsonValueProcessor:判断是否存在@ApolloJsonValue
AutoUpdateConfigChangeListener
当配置属性发生了变更,会更新到Apollo维护的配置属性(Environment的PropertySource引用了配置属性),因此Environment维护的属性也是最新的。然后Apollo会把变更的key丢给AutoUpdateConfigChangeListener,通过SpringValueRegistry查询key对应的SpringValue,拿到Spring bean,通过反射设置bean的属性,这样就更新了@Value标识的属性。