无题
无题
John DoeApollo
1. Google Guice
概念:Guice 是 google 开源的轻量级依赖注入框架(DI),类似于重量级的Spring IOC的DI。所以对于轻量级的应用,Guice比较合适。
- Guice:整个框架的门面
- Injector:一个依赖的管理上下文
- Binder:一个接口和实现的绑定
- Module:一组 Binder
- Provider:bean 的提供者
- Key:Binder 中对应一个 Provider
- Scope:Provider 的作用域
Binding
1 | public interface Binding<T> extends Element { |
- 键 Key
唯一地确定每一个绑定。 键 Key 包含了客户代码所依赖的类型以及一个可选的标注。你可以使用标注来区分指向同一类型的多个绑定。 - 生成T类型实例的工厂
Module:继承AbstractModule来生产Binding对象,该步骤在com.google.inject.internal.InternalInjectorCreator#injectDynamically完成
1 | public class BasicModule extends AbstractModule { |
由 Guice 创建Injector,可以从Injector中获取Binding,Instance,Provider
1 | public interface Injector { |
Binding生成过程解析
- com.google.inject.Guice#createInjector(com.google.inject.Stage, java.lang.Iterable<? extends com.google.inject.Module>)
- new InternalInjectorCreator().stage(stage).addModules(modules).build()
- com.google.inject.internal.InjectorShell.Builder#build
- com.google.inject.internal.AbstractProcessor#process(com.google.inject.internal.InjectorImpl, java.util.List<com.google.inject.spi.Element>)
- com.google.inject.spi.Element#acceptVisitor
- com.google.inject.spi.ScopeBinding#acceptVisitor
- com.google.inject.internal.ScopeBindingProcessor#visit
- com.google.inject.internal.State#putScopeBinding
- com.google.inject.internal.InheritingState#putScopeBinding / com.google.inject.internal.InheritingState#putBinding
但是如果配置的Binding属性时有 bind(Communication.class).toInstance(new Communication(true)).asEagerSingleton();则会创建并实例化对象
- com.google.inject.internal.InternalInjectorCreator#build
- com.google.inject.internal.InternalInjectorCreator#injectDynamically
- com.google.inject.internal.InternalInjectorCreator#loadEagerSingletons
2. Apollo 模块解析
- Config Service提供配置的读取、推送等功能,服务对象是Apollo客户端
- Admin Service提供配置的修改、发布等功能,服务对象是Apollo Portal(管理界面)
- Client通过域名访问Meta Server获取Config Service服务列表(IP+Port),而后直接通过IP+Port访问服务,同时在Client侧会做load balance、错误重试
3. Client 流程分析
将于Spring整合的自动配置类写入spring.factories
ApolloApplicationContextInitializer 继承自 Spring的 ApplicationContextInitializer 和 EnvironmentPostProcessor
ApolloApplicationContextInitializer 创建的时候创建 SpringInjector,Spring注入了 SpringModule 模块,该模块绑定了如下Binding
1
2
3bind(PlaceholderHelper.class).in(Singleton.class);
bind(ConfigPropertySourceFactory.class).in(Singleton.class);
bind(SpringValueRegistry.class).in(Singleton.class);EnvironmentPostProcessor 在Spring 环境创建结束执行com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer#postProcessEnvironment
com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer#initialize(org.springframework.core.env.ConfigurableEnvironment)
利用ApolloModule 创建DefaultInjector
1
2
3
4
5
6
7
8
9bind(ConfigManager.class).to(DefaultConfigManager.class).in(Singleton.class); // 配置管理
bind(ConfigFactoryManager.class).to(DefaultConfigFactoryManager.class).in(Singleton.class); // 配置工厂管理,可基于 Namespace 获得配置工厂
bind(ConfigRegistry.class).to(DefaultConfigRegistry.class).in(Singleton.class); // 管理 ConfigFactory 和 Namespace 的映射关系
bind(ConfigFactory.class).to(DefaultConfigFactory.class).in(Singleton.class); // 默认的配置工厂
bind(ConfigUtil.class).in(Singleton.class);
bind(HttpUtil.class).in(Singleton.class);
bind(ConfigServiceLocator.class).in(Singleton.class);
bind(RemoteConfigLongPollService.class).in(Singleton.class);
bind(YamlParser.class).in(Singleton.class);ConfigService 初始化
- ConfigService#getManager → ApolloInjector.getInstance(ConfigManager.class)
- DefaultConfigManager#DefaultConfigManager → ApolloInjector.getInstance(ConfigFactoryManager.class)
- DefaultConfigFactoryManager#DefaultConfigFactoryManager → ApolloInjector.getInstance(ConfigRegistry.class)
ConfigService.getConfig(namespace) 流程
ConfigService#getManager → ConfigManager
ConfigManager#getConfig → Config
DefaultConfigManager#m_configs中获取,有则返回
ConfigFactoryManager#getFactory
m_factoryManager.getFactory(namespace)
config = factory.create(namespace)
DefaultConfigFactory#create
DefaultConfigFactory#createLocalConfigRepository
DefaultConfigFactory#createLocalConfigRepository
DefaultConfigFactory#createRemoteConfigRepository
RemoteConfigRepository#RemoteConfigRepository
定时配置拉取任务schedulePeriodicRefresh,配置变化之后调用 AbstractConfigRepository#fireRepositoryChange通知
长轮询拉取配置 RemoteConfigRepository#scheduleLongPollingRefresh → while (!m_longPollingStopped.get() && !Thread.currentThread().isInterrupted())
RemoteConfigLongPollService#doLongPollingRefresh → RemoteConfigLongPollService#notify
配置变更监听器
- Config#addChangeListener(com.ctrip.framework.apollo.ConfigChangeListener, java.util.Set<java.lang.String>, java.util.Set<java.lang.String>)
- m_listeners.add(listener)
- AbstractConfigRepository#fireRepositoryChange配置变更后一次通知Config的监听器对配置变更响应





