相关阅读
简介
本文基于Spring Boot 2.6.6
,dubbo-spring-boot-starter 3.0.6
环境。
Dubbo借助DubboConfigInitEvent
事件完成初始化,事件DubboConfigInitEvent
的处理主要分为两步:
- 实例化
DubboConfigBeanInitializer
,DubboConfigBeanInitializer
是Dubbo用于初始化配置Bean,Dubbo的配置Bean需要在所有BeanPostProcessor
注册以后才可以被初始化; - 准备
ModuleDeployer
,用于发布Module
;
借助Spring Boot的事件发布机制,Dubbo实现了事件DubboConfigInitEvent
,在ReferenceAnnotationBeanPostProcessor.postProcessBeanFactory
中被发布(此时还不存在ApplicationEventMulticaster
,故缓存到早期事件earlyApplicationEvents
),在AbstractApplicationContext.registerListeners
(在AbstractApplicationContext.registerBeanPostProcessors
之后)中作为早期事件被处理;
Demo
测试环境基于Spring Boot 2.6.6;
核心依赖:
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.0.6</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>3.0.6</version>
</dependency>
核心配置参数:
server:
port: 8080
dubbo:
application:
id: dubbo-provider
name: dubbo-provider
registry:
address: zookeeper://127.0.0.1:2181
protocol:
port: 20880
scan:
base-packages: dubbo.producer.demo.service.impl
DubboConfigInitEvent
发布DubboConfigInitEvent
在PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
方法中,会执行容器中所有BeanFactoryPostProcessor
的处理,执行顺序大致如下:
- 实现了
PriorityOrdered
的BeanDefinitionRegistryPostProcessor
; - 实现了
Ordered
的BeanDefinitionRegistryPostProcessor
; - 剩下的
BeanDefinitionRegistryPostProcessor
; - 实现了
PriorityOrdered
的BeanFactoryPostProcessor
; - 实现了
Ordered
的BeanFactoryPostProcessor
; - 剩下的
BeanFactoryPostProcessor
;
注意:BeanFactoryPostProcessor
的获取途径有两种:代码直接添加和配置(代码配置或者文件配置),这里分析的执行顺序没有考虑这两种途径的区别;
ConfigurationClassPostProcessor
实现了BeanDefinitionRegistryPostProcessor
和PriorityOrdered
,所以它会先执行其postProcessBeanDefinitionRegistry
逻辑,从而引入了DubboAutoConfiguration
自动配置类,由上文可知,DubboAutoConfiguration
自动配置会调用到DubboBeanUtils.registerCommonBeans
,该方法内会注册ReferenceAnnotationBeanPostProcessor
的RootBeanDefinition
;
ReferenceAnnotationBeanPostProcessor
实现了BeanFactoryPostProcessor
和Ordered
,故在第五步时,会引入ReferenceAnnotationBeanPostProcessor
并执行其postProcessBeanFactory
方法;
ReferenceAnnotationBeanPostProcessor.postProcessBeanFactory
方法中会发布DubboConfigInitEvent
事件,代码如下:
applicationContext.publishEvent(new DubboConfigInitEvent(applicationContext));
此时,AbstractApplicationContext
中还不存在ApplicationEventMulticaster
,所以还无法真正发布事件,便先缓存到earlyApplicationEvents
中,等初始化ApplicationEventMulticaster
后再发布事件;
AbstractApplicationContext
执行initApplicationEventMulticaster
完成初始化ApplicationEventMulticaster
后,便可以发布事件了,紧接着执行registerListeners
,代码如下:
protected void registerListeners() {
// 添加已存在的ApplicationListener
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 添加存在的ApplicationListener BeanName
// 此时包含:org.apache.dubbo.config.spring.context.DubboConfigApplicationListener
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 发布缓存的早期事件
// 此时包含DubboConfigInitEvent
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
处理DubboConfigInitEvent
ApplicationEvent
由ApplicationEventMulticaster.multicastEvent
,默认实现为SimpleApplicationEventMulticaster
,其代码如下:
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
// 获取支持本事件的ApplicationListener
// 支持DubboConfigInitEvent:DubboConfigApplicationListener
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
// 执行监听器
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 处理事件
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
// 异常处理
...
}
}
getApplicationListeners
方法中会将支持DubboConfigInitEvent
的DubboConfigApplicationListener
实例化返回,然后执行其onApplicationEvent
,代码如下:
public void onApplicationEvent(DubboConfigInitEvent event) {
if (nullSafeEquals(applicationContext, event.getSource())) {
// 如果已经初始化过,则无需再初始化
if (initialized.compareAndSet(false, true)) {
// 初始化配置Bean
initDubboConfigBeans();
}
}
}
private void initDubboConfigBeans() {
if (applicationContext.containsBean(DubboConfigBeanInitializer.BEAN_NAME)) {
// 实例化DubboConfigBeanInitializer
// DubboConfigBeanInitializer的RootBeanDefinition在DubboBeanUtils.registerCommonBeans中注册,由DubboAutoConfiguration触发
applicationContext.getBean(DubboConfigBeanInitializer.BEAN_NAME, DubboConfigBeanInitializer.class);
} else {
logger.warn("Bean '" + DubboConfigBeanInitializer.BEAN_NAME + "' was not found");
}
// ModuleDeployer初始化
moduleModel.getDeployer().prepare();
}
DubboConfigBeanInitializer
DubboConfigBeanInitializer
实现了接口InitializingBean
,故实例化时会调用其afterPropertiesSet
方法,代码如下:
public void afterPropertiesSet() throws Exception {
init();
}
private void init() {
// 如果已经初始化过,则无需再初始化
if (initialized.compareAndSet(false, true)) {
// 实例化ReferenceBeanManager
// ReferenceBeanManager的RootBeanDefinition在DubboBeanUtils.registerCommonBeans中注册,由DubboAutoConfiguration触发
referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);
try {
// 初始化配置Bean
prepareDubboConfigBeans();
// 初始化ReferenceBean
referenceBeanManager.prepareReferenceBeans();
} catch (Throwable e) {
throw new FatalBeanException("Initialization dubbo config beans failed", e);
}
}
}
private void prepareDubboConfigBeans() {
logger.info("loading dubbo config beans ...");
// 加载各种配置Bean,并注册到configManager
loadConfigBeansOfType(ApplicationConfig.class, configManager);
loadConfigBeansOfType(RegistryConfig.class, configManager);
loadConfigBeansOfType(ProtocolConfig.class, configManager);
loadConfigBeansOfType(MonitorConfig.class, configManager);
loadConfigBeansOfType(ConfigCenterBean.class, configManager);
loadConfigBeansOfType(MetadataReportConfig.class, configManager);
loadConfigBeansOfType(MetricsConfig.class, configManager);
loadConfigBeansOfType(SslConfig.class, configManager);
// 加载Module配置Bean,并注册到moduleConfigManager
loadConfigBeansOfType(ModuleConfig.class, moduleModel.getConfigManager());
loadConfigBeansOfType(ProviderConfig.class, moduleModel.getConfigManager());
loadConfigBeansOfType(ConsumerConfig.class, moduleModel.getConfigManager());
// 加载ConfigCenterBean
List<ConfigCenterBean> configCenterBeans = configManager.loadConfigsOfTypeFromProps(ConfigCenterBean.class);
for (ConfigCenterBean configCenterBean : configCenterBeans) {
String beanName = configCenterBean.getId() != null ? configCenterBean.getId() : "configCenterBean";
beanFactory.initializeBean(configCenterBean, beanName);
}
logger.info("dubbo config beans are loaded.");
}
private void loadConfigBeansOfType(Class<? extends AbstractConfig> configClass, AbstractConfigManager configManager) {
// 获取容器中configClass类型的BeanName
String[] beanNames = beanFactory.getBeanNamesForType(configClass, true, false);
for (String beanName : beanNames) {
// 实例化configClass
AbstractConfig configBean = beanFactory.getBean(beanName, configClass);
// 注册configBean
configManager.addConfig(configBean);
}
}
本次测试环境下,由于未注册相关配置Bean的RootBeanDefinition
,所以prepareDubboConfigBeans
并没有加载任何Bean;
接下来就是执行referenceBeanManager.prepareReferenceBeans()
,代码如下:
public void prepareReferenceBeans() throws Exception {
// 设置初始化标识
// 这样后续添加ReferenceBean就可以立即初始化
initialized = true;
for (ReferenceBean referenceBean : getReferences()) {
// 初始化提前添加的ReferenceBean
initReferenceBean(referenceBean);
}
}
至此,DubboConfigBeanInitializer
实例化就结束了,Dubbo借助其完成相关Bean(如果存在的话)的实例化;
ModuleDeployer
在DubboConfigApplicationListener.initDubboConfigBeans
方法中,除了实例化DubboConfigBeanInitializer
外,还有很重要的操作,即moduleModel.getDeployer().prepare()
,此处ModuleDeployer
实现类为DefaultModuleDeployer
,其prepare
方法代码如下:
public void prepare() {
// 先初始化Application
applicationDeployer.initialize();
// 再初始化Module
this.initialize();
}
准备工作分为两步:
- 初始化Application;
- 初始化Module;
初始化Application
applicationDeployer
的实现为DefaultApplicationDeployer
,其initialize
方法代码如下:
public void initialize() {
if (initialized) {
// 如果已经初始化过,则直接退出
return;
}
synchronized (startLock) {
// 再次确认是否已经完成初始化,确保并发安全
if (initialized) {
return;
}
// 注册DubboShutdownHook
registerShutdownHook();
// 开启配置中心
startConfigCenter();
// 加载Application相关配置
loadApplicationConfigs();
// 初始化相关ModuleModel
initModuleDeployers();
// 开启元数据中心
startMetadataCenter();
// 设置初始化标识
initialized = true;
if (logger.isInfoEnabled()) {
logger.info(getIdentifier() + " has been initialized!");
}
}
}
开启配置中心
代码如下:
private void startConfigCenter() {
// 从配置文件中加载ApplicationConfig信息
// 配置参数前缀为:dubbo.application
configManager.loadConfigsOfTypeFromProps(ApplicationConfig.class);
if (StringUtils.isBlank(applicationModel.getModelName())) {
applicationModel.setModelName(applicationModel.tryGetApplicationName());
}
// 从配置文件中加载ConfigCenterConfig信息
// 配置参数前缀为:dubbo.config-center
configManager.loadConfigsOfTypeFromProps(ConfigCenterConfig.class);
// 如果没有有效ConfigCenterConfig,则使用默认RegistryConfig作为ConfigCenterConfig
// RegistryConfig也会从配置文件中加载
// 配置参数前缀为:dubbo.registry
useRegistryAsConfigCenterIfNecessary();
// 如果此时还没有ConfigCenterConfig,那就会创建一个出来
Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
if (CollectionUtils.isEmpty(configCenters)) {
ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
configCenterConfig.setScopeModel(applicationModel);
configCenterConfig.refresh();
ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
if (configCenterConfig.isValid()) {
configManager.addConfigCenter(configCenterConfig);
configCenters = configManager.getConfigCenters();
}
} else {
for (ConfigCenterConfig configCenterConfig : configCenters) {
// 刷新配置
configCenterConfig.refresh();
// 校验参数
ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
}
}
if (CollectionUtils.isNotEmpty(configCenters)) {
CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
for (ConfigCenterConfig configCenter : configCenters) {
environment.updateExternalConfigMap(configCenter.getExternalConfiguration());
environment.updateAppExternalConfigMap(configCenter.getAppExternalConfiguration());
// 此时会创建DynamicConfiguration实例,连接该configCenter
compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter));
}
environment.setDynamicConfiguration(compositeDynamicConfiguration);
}
}
加载Application相关配置
代码如下:
private void loadApplicationConfigs() {
// 从配置文件中加载配置信息
configManager.loadConfigs();
}
// ConfigManager.java
public void loadConfigs() {
// ApplicationConfig已经在DefaultApplicationDeployer.startConfigCenter中加载过了,故会跳过
loadConfigsOfTypeFromProps(ApplicationConfig.class);
// 从配置文件中加载MonitorConfig信息
// 配置参数前缀为:dubbo.monitor
loadConfigsOfTypeFromProps(MonitorConfig.class);
// 从配置文件中加载MetricsConfig信息
// 配置参数前缀为:dubbo.metrics
loadConfigsOfTypeFromProps(MetricsConfig.class);
// 从配置文件中加载ProtocolConfig信息
// 配置参数前缀为:dubbo.protocol
loadConfigsOfTypeFromProps(ProtocolConfig.class);
// RegistryConfig已经在DefaultApplicationDeployer.startConfigCenter中加载过了,故会跳过
loadConfigsOfTypeFromProps(RegistryConfig.class);
// 从配置文件中加载MetadataReportConfig信息
// 配置参数前缀为:dubbo.metadata-report
loadConfigsOfTypeFromProps(MetadataReportConfig.class);
// config centers has bean loaded before starting config center
//loadConfigsOfTypeFromProps(ConfigCenterConfig.class);
// 刷新配置如果存在的话
refreshAll();
// 校验配置
// 1. 某配置不存在但是必须就会创建该配置
// 2. 配置存在ConfigValidator,则调用ConfigValidator.validate进行校验
// 3. 同一个端口不能有重复的ProtocolConfig
checkConfigs();
if (StringUtils.isBlank(applicationModel.getModelName())) {
applicationModel.setModelName(applicationModel.getApplicationName());
}
}
初始化相关ModuleModel
代码如下:
private void initModuleDeployers() {
// 确保默认Module存在
// 不存在就会创建
applicationModel.getDefaultModule();
// copy modules and initialize avoid ConcurrentModificationException if add new module
List<ModuleModel> moduleModels = new ArrayList<>(applicationModel.getModuleModels());
for (ModuleModel moduleModel : moduleModels) {
// 初始化相关Module
moduleModel.getDeployer().initialize();
}
}
开启元数据中心
代码如下:
private void startMetadataCenter() {
// 如果没有有效MetadataCenter,则使用默认RegistryConfig作为ConfigCenterConfig
useRegistryAsMetadataCenterIfNecessary();
ApplicationConfig applicationConfig = getApplication();
String metadataType = applicationConfig.getMetadataType();
Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
if (CollectionUtils.isEmpty(metadataReportConfigs)) {
if (REMOTE_METADATA_STORAGE_TYPE.equals(metadataType)) {
throw new IllegalStateException("No MetadataConfig found, Metadata Center address is required when 'metadata=remote' is enabled.");
}
return;
}
// 初始化MetadataReportInstance
MetadataReportInstance metadataReportInstance = applicationModel.getBeanFactory().getBean(MetadataReportInstance.class);
List<MetadataReportConfig> validMetadataReportConfigs = new ArrayList<>(metadataReportConfigs.size());
for (MetadataReportConfig metadataReportConfig : metadataReportConfigs) {
ConfigValidationUtils.validateMetadataConfig(metadataReportConfig);
if (!metadataReportConfig.isValid()) {
logger.warn("Ignore invalid metadata-report config: " + metadataReportConfig);
continue;
}
validMetadataReportConfigs.add(metadataReportConfig);
}
metadataReportInstance.init(validMetadataReportConfigs);
if (!metadataReportInstance.inited()) {
throw new IllegalStateException(String.format("%s MetadataConfigs found, but none of them is valid.", metadataReportConfigs.size()));
}
}
初始化Module
DefaultModuleDeployer.initialize
方法代码如下:
public void initialize() throws IllegalStateException {
if (initialized) {
// 如果已经初始化过,则直接退出
return;
}
synchronized (this) {
// 再次确认是否已经完成初始化,确保并发安全
if (initialized) {
return;
}
// 加载配置:ProviderConfig、ConsumerConfig、ModuleConfig
loadConfigs();
ModuleConfig moduleConfig = moduleModel.getConfigManager().getModule().orElseThrow(() -> new IllegalStateException("Default module config is not initialized"));
exportAsync = Boolean.TRUE.equals(moduleConfig.getExportAsync());
referAsync = Boolean.TRUE.equals(moduleConfig.getReferAsync());
// start in background
background = moduleConfig.getBackground();
if (background == null) {
// compatible with old usages
background = isExportBackground() || isReferBackground();
}
// 设置初始化标识
initialized = true;
if (logger.isInfoEnabled()) {
logger.info(getIdentifier() + " has been initialized!");
}
}
}
加载配置
代码如下:
private void loadConfigs() {
// load module configs
moduleModel.getConfigManager().loadConfigs();
moduleModel.getConfigManager().refreshAll();
}
// ModuleConfigManager.java
public void loadConfigs() {
// 从配置文件中加载ProviderConfig信息
// 配置参数前缀为:dubbo.provider
loadConfigsOfTypeFromProps(ProviderConfig.class);
// 从配置文件中加载ConsumerConfig信息
// 配置参数前缀为:dubbo.consumer
loadConfigsOfTypeFromProps(ConsumerConfig.class);
// 从配置文件中加载ModuleConfig信息
// 配置参数前缀为:dubbo.module
loadConfigsOfTypeFromProps(ModuleConfig.class);
// 校验配置
// 1. 某配置不存在但是必须就会创建该配置
// 2. 配置存在ConfigValidator,则调用ConfigValidator.validate进行校验
checkDefaultAndValidateConfigs(ProviderConfig.class);
checkDefaultAndValidateConfigs(ConsumerConfig.class);
checkDefaultAndValidateConfigs(ModuleConfig.class);
}
public void refreshAll() {
// 刷新配置
getModule().ifPresent(ModuleConfig::refresh);
getProviders().forEach(ProviderConfig::refresh);
getConsumers().forEach(ConsumerConfig::refresh);
getReferences().forEach(ReferenceConfigBase::refresh);
getServices().forEach(ServiceConfigBase::refresh);
}