【二】dubbo源码分析之服务提供方启动(注解方式启动spring+dubbo)

it2024-12-15  19

一、测试使用代码

https://github.com/apache/dubbo-samples.git

2.6.X分支

服务提供方代码:

package org.apache.dubbo.samples.annotation.impl; import org.apache.dubbo.samples.api.client.HelloService; import com.alibaba.dubbo.config.annotation.Service; @Service public class AnnotationHelloServiceImpl implements HelloService { public String sayHello(String name) { System.out.println("greeting service received: " + name); return "hello, " + name; } }

服务提供方的启动代码:

package org.apache.dubbo.samples.annotation; import com.alibaba.dubbo.config.ApplicationConfig; import com.alibaba.dubbo.config.ProtocolConfig; import com.alibaba.dubbo.config.ProviderConfig; import com.alibaba.dubbo.config.RegistryConfig; import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo; import org.apache.dubbo.samples.annotation.support.EmbeddedZooKeeper; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; public class AnnotationProviderBootstrap { public static void main(String[] args) throws Exception { new EmbeddedZooKeeper(2181, false).start(); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class); context.start(); System.in.read(); } @Configuration @EnableDubbo(scanBasePackages = "org.apache.dubbo.samples.annotation.impl") static class ProviderConfiguration { @Bean public ProviderConfig providerConfig() { ProviderConfig providerConfig = new ProviderConfig(); providerConfig.setTimeout(1000); return providerConfig; } @Bean public ApplicationConfig applicationConfig() { ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setName("dubbo-annotation-provider"); return applicationConfig; } @Bean public RegistryConfig registryConfig() { RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setProtocol("zookeeper"); registryConfig.setAddress("localhost"); registryConfig.setPort(2181); return registryConfig; } @Bean public ProtocolConfig protocolConfig() { ProtocolConfig protocolConfig = new ProtocolConfig(); protocolConfig.setName("dubbo"); protocolConfig.setPort(20880); return protocolConfig; } } }

 二、启动简介

 AbstractApplicationContext的refresh方法为总入口的例子展示dubbo在spring refresh的各个阶段做的事

public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //这里进行含有@Service的beanDefinition的注册 //也注册每个@Service对应的ServiceBean invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //实例化和初始化所有非懒加载的@Service finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. // 在此处使用publishEvent,加载dubbo服务 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }

主要关注三个阶段点:

1. invokeBeanFactoryPostProcessors(beanFactory);

这里进行含有@Service的beanDefinition的注册、也注册每个@Service对应的ServiceBean

2. finishBeanFactoryInitialization(beanFactory);

实例化和初始化所有非懒加载的@Service

3. finishRefresh();    

在此处使用publishEvent,加载dubbo服务                 

三、注册含有@Service的beanDefinition、注册每个@Service对应的ServiceBean

@EnableDubbo

由启动代码可见,使用了注解@EnableDubbo,点进去看该注解的实现

发现用到了@EnableDubboConfig和@DubboComponentScan。

而@EnableDubboConfig中有@Import(DubboConfigConfigurationRegistrar.class)

@DubboComponentScan中有@Import(DubboComponentScanRegistrar.class)

启动,开始debug。

熟悉spring的应该知道,启动后,在著名的AbstractApplicationContext类的著名的方法refresh中,会调用著名的

invokeBeanFactoryPostProcessors(beanFactory);方法,而这个里面又是使用著名的ConfigurationClassPostProcessor类来做的扫描bean和注册bean到spring容器中。那这里就会调用到DubboConfigConfigurationRegistrar的registerBeanDefinitions方法。

DubboConfigConfigurationRegistrar

registerBeanDefinitions方法

public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AnnotationAttributes attributes = AnnotationAttributes.fromMap( importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName())); boolean multiple = attributes.getBoolean("multiple"); // Single Config Bindings registerBeans(registry, DubboConfigConfiguration.Single.class); if (multiple) { // Since 2.6.6 https://github.com/apache/incubator-dubbo/issues/3193 registerBeans(registry, DubboConfigConfiguration.Multiple.class); } } }

做了1件事:

往BeanDefinitionRegistry中注册了两个class,是DubboConfigConfiguration.Single.class和DubboConfigConfiguration.Multiple.class

DubboConfigConfiguration

package com.alibaba.dubbo.config.spring.context.annotation; import com.alibaba.dubbo.config.AbstractConfig; import com.alibaba.dubbo.config.ApplicationConfig; import com.alibaba.dubbo.config.ConsumerConfig; import com.alibaba.dubbo.config.ModuleConfig; import com.alibaba.dubbo.config.MonitorConfig; import com.alibaba.dubbo.config.ProtocolConfig; import com.alibaba.dubbo.config.ProviderConfig; import com.alibaba.dubbo.config.RegistryConfig; import org.springframework.context.annotation.Configuration; /** * Dubbo {@link AbstractConfig Config} {@link Configuration} * * @see Configuration * @see EnableDubboConfigBindings * @see EnableDubboConfigBinding * @see ApplicationConfig * @see ModuleConfig * @see RegistryConfig * @see ProtocolConfig * @see MonitorConfig * @see ProviderConfig * @see ConsumerConfig * @since 2.5.8 */ public class DubboConfigConfiguration { /** * Single Dubbo {@link AbstractConfig Config} Bean Binding */ @EnableDubboConfigBindings({ @EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.module", type = ModuleConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.registry", type = RegistryConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.monitor", type = MonitorConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.provider", type = ProviderConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class) }) public static class Single { } /** * Multiple Dubbo {@link AbstractConfig Config} Bean Binding */ @EnableDubboConfigBindings({ @EnableDubboConfigBinding(prefix = "dubbo.applications", type = ApplicationConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.modules", type = ModuleConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.registries", type = RegistryConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.protocols", type = ProtocolConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.monitors", type = MonitorConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.providers", type = ProviderConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.consumers", type = ConsumerConfig.class, multiple = true) }) public static class Multiple { } }

 那我们可以看到DubboConfigConfiguration中的Single和Multiple都使用了一个注解@EnableDubboConfigBindings

@EnableDubboConfigBindings 

该注解中用到了DubboConfigBindingsRegistrar

 DubboConfigBindingsRegistrar

package com.alibaba.dubbo.config.spring.context.annotation; import com.alibaba.dubbo.config.AbstractConfig; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.EnvironmentAware; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.Assert; /** * {@link AbstractConfig Dubbo Config} binding Bean registrar for {@link EnableDubboConfigBindings} * * @see EnableDubboConfigBindings * @see DubboConfigBindingRegistrar * @since 2.5.8 */ public class DubboConfigBindingsRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware { private ConfigurableEnvironment environment; @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AnnotationAttributes attributes = AnnotationAttributes.fromMap( importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBindings.class.getName())); AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value"); DubboConfigBindingRegistrar registrar = new DubboConfigBindingRegistrar(); registrar.setEnvironment(environment); for (AnnotationAttributes element : annotationAttributes) { registrar.registerBeanDefinitions(element, registry); } } @Override public void setEnvironment(Environment environment) { Assert.isInstanceOf(ConfigurableEnvironment.class, environment); this.environment = (ConfigurableEnvironment) environment; } }

这个类的方法,后面在解析 DubboConfigConfiguration.Single类和Multiple类的@EnableDubboConfigBindings中的@import(DubboConfigBindingsRegistrar.class)时会调用到,换句话说调了两次

 做了1件事

找出

prefix = "dubbo.application", type = ApplicationConfig.class prefix = "dubbo.module", type = ModuleConfig.class prefix = "dubbo.registry", type = RegistryConfig.class prefix = "dubbo.protocol", type = ProtocolConfig.class prefix = "dubbo.monitor", type = MonitorConfig.class prefix = "dubbo.provider", type = ProviderConfig.class prefix = "dubbo.consumer"

这些类然后注册。

跟进去看注册的方法:

DubboConfigBindingRegistrar类

protected void registerBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry) { String prefix = environment.resolvePlaceholders(attributes.getString("prefix")); Class<? extends AbstractConfig> configClass = attributes.getClass("type"); boolean multiple = attributes.getBoolean("multiple"); registerDubboConfigBeans(prefix, configClass, multiple, registry); }

 再跟进去registerDubboConfigBeans方法

private void registerDubboConfigBeans(String prefix, Class<? extends AbstractConfig> configClass, boolean multiple, BeanDefinitionRegistry registry) { Map<String, Object> properties = getSubProperties(environment.getPropertySources(), prefix); if (CollectionUtils.isEmpty(properties)) { if (log.isDebugEnabled()) { log.debug("There is no property for binding to dubbo config class [" + configClass.getName() + "] within prefix [" + prefix + "]"); } return; } Set<String> beanNames = multiple ? resolveMultipleBeanNames(properties) : Collections.singleton(resolveSingleBeanName(properties, configClass, registry)); for (String beanName : beanNames) { registerDubboConfigBean(beanName, configClass, registry); registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry); } registerDubboConfigBeanCustomizers(registry); }

 此处主要做了两件事

1. 注册@EnableDubboConfigBinding上的各种Config

2. 注册多个用于处理各种Config的DubboConfigBindingBeanPostProcessor

 我debug的时候,其实第一个return就返回了,并没有出发后面的代码。原因:

 

事件

注意事项

beanName

注册ApplicationConfig的beanDefinition

无配置dubbo.application的相关配置时,则不注册bean

org.apache.dubbo.config.ApplicationConfig#0

注册ModuleConfig的beanDefinition

无配置dubbo.module的相关配置时,则不注册bean

org.apache.dubbo.config.ModuleConfig#0

注册RegistryConfig的beanDefinition

无配置dubbo.registry的相关配置时,则不注册bean

org.apache.dubbo.config.RegistryConfig#0

注册ProtocolConfig的beanDefinition

无配置dubbo.protocol的相关配置时,则不注册bean

org.apache.dubbo.config.ProtocolConfig#0

注册MonitorConfig的beanDefinition

无配置dubbo.monitor的相关配置时,则不注册bean

org.apache.dubbo.config.MonitorConfig#0

注册ProviderConfig的beanDefinition

无配置dubbo.provider的相关配置时,则不注册bean

org.apache.dubbo.config.ProviderConfig#0

注册ConsumerConfig的beanDefinition

无配置dubbo.consumer的相关配置时,则不注册bean

org.apache.dubbo.config.ConsumerConfig#0

 

DubboComponentScanRegistrar类的registerBeanDefinitions方法

@Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //得到要扫描的路径 Set<String> packagesToScan = getPackagesToScan(importingClassMetadata); registerServiceAnnotationBeanPostProcessor(packagesToScan, registry); registerReferenceAnnotationBeanPostProcessor(registry); }

 做了3件事:

1.得到要扫描的路径,此处是org.apache.dubbo.samples.annotation.impl

2.注册ServiceAnnotationBeanPostProcessor  它其实是个beanFactoryPostProcessor

3.注册ReferenceAnnotationBeanPostProcessor  它其实是个beanFactoryPostProcessor

ServiceAnnotationBeanPostProcessor

该类的方法postProcessBeanDefinitionRegistry会在ConfigurationClassPostProcessor完成之后调用

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { //这里的值就是org.apache.dubbo.samples.annotation.impl Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan); if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) { //这是重点,扫描并注册所有的ServiceBean registerServiceBeans(resolvedPackagesToScan, registry); } else { if (logger.isWarnEnabled()) { logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!"); } } }

 其实就是做了一件事,扫描org.apache.dubbo.samples.annotation.impl下的所有ServiceBean并且注册

跟进去看这个registerServiceBeans方法

private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) { // 定义扫描器 DubboClassPathBeanDefinitionScanner scanner = new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader); BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry); scanner.setBeanNameGenerator(beanNameGenerator); // 定义需要包含的过滤器 scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class)); for (String packageToScan : packagesToScan) { // Registers @Service Bean first scanner.scan(packageToScan); // Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not. 扫描出所有的标注了@org.apache.dubbo.config.annotation.Service的Bean Set<BeanDefinitionHolder> beanDefinitionHolders = findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator); if (!CollectionUtils.isEmpty(beanDefinitionHolders)) { for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) { // 利用上面扫描出来的bean,再分别注册一个类型为ServiceBean的bean,其中有一个属性ref,指向真正的@Service的bean registerServiceBean(beanDefinitionHolder, registry, scanner); } if (logger.isInfoEnabled()) { logger.info(beanDefinitionHolders.size() + " annotated Dubbo's @Service Components { " + beanDefinitionHolders + " } were scanned under package[" + packageToScan + "]"); } } else { if (logger.isWarnEnabled()) { logger.warn("No Spring Bean annotating Dubbo's @Service was found under package[" + packageToScan + "]"); } } } }

做了几件事

1.定义扫描器、过滤器

2. 扫描出所有的标注了@org.apache.dubbo.config.annotation.Service的Bean

3.利用上面扫描出来的@org.apache.dubbo.config.annotation.Service的Bean,再分别注册一个类型为ServiceBean的bean,其中有一个属性ref,指向真正的@Service的bean

ServiceBean注册

对于ServiceBean,其是Dubbo提供对外服务的核心,该类会将每一个Dubbo类型的bean都注册到zookeeper上,以便其他的服务通过zookeeper获取该类的信息,然后通过TCP协议进行远程调用。

关于ServiceBean的工作原理,我们后续会进行详细讲解,这里主要讲解其是如何注册到BeanDefinitionRegistry中的。

在registerServiceBean()方法中为这每一个BeanDefinition创建一个ServiceBean的BeanDefinition,并且其ref属性指向了这些@Service标注的class对应的实例。

private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry, DubboClassPathBeanDefinitionScanner scanner) { // 获取目标bean的class对象 Class<?> beanClass = resolveClass(beanDefinitionHolder); // 查找该class上标注的@Service注解对象 Service service = findAnnotation(beanClass, Service.class); // 获取目标bean所实现的接口对象 Class<?> interfaceClass = resolveServiceInterfaceClass(beanClass, service); String annotatedServiceBeanName = beanDefinitionHolder.getBeanName(); // 根据@Service注解中的各个属性,为ServiceBean构造一个BeanDefinition对象 AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName); // 为当前ServiceBean生成一个名称 // ServiceBean Bean name String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName); // 判断当前BeanDefinitionRegistry中是否已经存在了当前名称的bean,如果存在,则不进行注册 if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean // 将当前ServiceBean对应的BeanDefinition注册到BeanDefinitionRegistry中 registry.registerBeanDefinition(beanName, serviceBeanDefinition); if (logger.isInfoEnabled()) { logger.info("The BeanDefinition[" + serviceBeanDefinition + "] of ServiceBean has been registered with name : " + beanName); } } else { if (logger.isWarnEnabled()) { logger.warn("The Duplicated BeanDefinition[" + serviceBeanDefinition + "] of ServiceBean[ bean name : " + beanName + "] was be found , Did @DubboComponentScan scan to same package in many times?"); } } }

做了几件事:

1.获取目标bean的class对象 

2.查找该class上标注的@Service注解对象

3.获取目标bean所实现的接口对象

4.根据@Service注解中的各个属性,为ServiceBean构造一个BeanDefinition对象

5.为当前ServiceBean生成一个名称

6.断当前BeanDefinitionRegistry中是否已经存在了当前名称的bean,如果存在,则不进行注册

7.将当前ServiceBean对应的BeanDefinition注册到BeanDefinitionRegistry中 

 

ReferenceAnnotationBeanPostProcessor

 这个类的onApplicationEvent什么时候被触发:

就是spring的refresh方法里面的finishRefresh();方法来触发。

既是spring的Bean都实例化初始化后通过finishRefresh中的publishEvent发送ContextRefreshedEvent事件来触发dubbo开始暴露export服务

标题五中会详细讲这个

 四、实例化初始化dubbo bean

入口是spring的refresh方法里面的finishBeanFactoryInitialization方法,里面getBean的时候

也就是说这里在初始化HelloService对应的ServiceBean

ServiceBean实现了InitializingBean所以,实例化ServiceBean后,在初始化阶段会调用ServiceBean的afterPropertiesSet方法

ServiceBean.afterPropertiesSet

public void afterPropertiesSet() throws Exception { //获取provider配置 if (getProvider() == null) { Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false); if (providerConfigMap != null && providerConfigMap.size() > 0) { Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false); if ((protocolConfigMap == null || protocolConfigMap.size() == 0) && providerConfigMap.size() > 1) { // backward compatibility List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>(); for (ProviderConfig config : providerConfigMap.values()) { if (config.isDefault() != null && config.isDefault().booleanValue()) { providerConfigs.add(config); } } if (!providerConfigs.isEmpty()) { setProviders(providerConfigs); } } else { ProviderConfig providerConfig = null; for (ProviderConfig config : providerConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (providerConfig != null) { throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config); } providerConfig = config; } } if (providerConfig != null) { setProvider(providerConfig); } } } } //获取application配置 if (getApplication() == null && (getProvider() == null || getProvider().getApplication() == null)) { Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false); if (applicationConfigMap != null && applicationConfigMap.size() > 0) { ApplicationConfig applicationConfig = null; for (ApplicationConfig config : applicationConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (applicationConfig != null) { throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config); } applicationConfig = config; } } if (applicationConfig != null) { setApplication(applicationConfig); } } } //获取module配置 if (getModule() == null && (getProvider() == null || getProvider().getModule() == null)) { Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false); if (moduleConfigMap != null && moduleConfigMap.size() > 0) { ModuleConfig moduleConfig = null; for (ModuleConfig config : moduleConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (moduleConfig != null) { throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config); } moduleConfig = config; } } if (moduleConfig != null) { setModule(moduleConfig); } } } //获取注册中心的配置 if ((getRegistries() == null || getRegistries().isEmpty()) && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().isEmpty()) && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty())) { Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false); if (registryConfigMap != null && registryConfigMap.size() > 0) { List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>(); for (RegistryConfig config : registryConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { registryConfigs.add(config); } } if (registryConfigs != null && !registryConfigs.isEmpty()) { super.setRegistries(registryConfigs); } } } //获取monitor配置 if (getMonitor() == null && (getProvider() == null || getProvider().getMonitor() == null) && (getApplication() == null || getApplication().getMonitor() == null)) { Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false); if (monitorConfigMap != null && monitorConfigMap.size() > 0) { MonitorConfig monitorConfig = null; for (MonitorConfig config : monitorConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (monitorConfig != null) { throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config); } monitorConfig = config; } } if (monitorConfig != null) { setMonitor(monitorConfig); } } } //获取protocol配置 if ((getProtocols() == null || getProtocols().isEmpty()) && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().isEmpty())) { Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>(); for (ProtocolConfig config : protocolConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { protocolConfigs.add(config); } } if (protocolConfigs != null && !protocolConfigs.isEmpty()) { super.setProtocols(protocolConfigs); } } } //获取<dubbo:service/>的path属性,path即服务的发布路径 if (getPath() == null || getPath().length() == 0) { if (beanName != null && beanName.length() > 0 && getInterface() != null && getInterface().length() > 0 && beanName.startsWith(getInterface())) { //如果没有设置path属性,则默认会以beanName作为path setPath(beanName); } } //是否延迟暴露 if (!isDelay()) { //进行服务暴露 export(); } }

做了几件事:

 1.获取provider配置

2.获取application配置

3.获取module配置

4.获取注册中心的配置

5.获取monitor配置

6.获取protocol配置

7.获取<dubbo:service/>的path属性,path即服务的发布路径。如果没有设置path属性,则默认会以beanName作为path

8.进行服务暴露

我debug的时候在这里是延迟暴露,所以没有走到export里面去。到等候第五步里面发送ContextRefreshedEvent事件后才会export 

五、publishEvent发送ContextRefreshedEvent事件来触发dubbo开始export

首先看一下哪些类监听了PublishEvent发出来的ContextRefreshedEvent事件

最先给ReferenceAnnotationBeanPostProcessor发送ContextRefreshedEvent事件

ReferenceAnnotationBeanPostProcessor

public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ServiceBeanExportedEvent) { onServiceBeanExportEvent((ServiceBeanExportedEvent) event); } else if (event instanceof ContextRefreshedEvent) { onContextRefreshedEvent((ContextRefreshedEvent) event); } }

这里我们能看到 ReferenceAnnotationBeanPostProcessor监听了两个事件:ContextRefreshedEventServiceBeanExportEvent

 然而ReferenceAnnotationBeanPostProcessor对ContextRefreshedEvent事件的处理是空方法

private void onContextRefreshedEvent(ContextRefreshedEvent event) { }

那么 ServiceBeanExportEvent事件是怎么触发的呢?

 是ServiceBean接收到了ContextRefreshedEvent事件后发出的ServiceBeanExportEvent事件

ServiceBean

那这里就会调用ServiceBean的onApplicationEvent方法

public void onApplicationEvent(ContextRefreshedEvent event) { if (isDelay() && !isExported() && !isUnexported()) { if (logger.isInfoEnabled()) { logger.info("The service ready on spring started. service: " + getInterface()); } export(); } }

跟进去会发现export()既是暴露服务的方法

public void export() { super.export(); // Publish ServiceBeanExportedEvent publishExportEvent(); }

做了两件事:

1.调用父类的export方法

2.发布ServiceBeanExportedEvent事件 

 调用父类的export方法(ServiceConfig.export)

ServiceConfig.export

public synchronized void export() { if (provider != null) { if (export == null) { export = provider.getExport(); } if (delay == null) { delay = provider.getDelay(); } } if (export != null && !export) { return; } if (delay != null && delay > 0) { delayExportExecutor.schedule(new Runnable() { @Override public void run() { doExport(); } }, delay, TimeUnit.MILLISECONDS); } else { doExport(); } }

这个export暴露的流程后面专门写一篇来讲,这篇不讲这个。 

发布ServiceBeanExportedEvent事件

这里面发了一个ServiceBeanExportedEvent事件

private void publishExportEvent() { ServiceBeanExportedEvent exportEvent = new ServiceBeanExportedEvent(this); applicationEventPublisher.publishEvent(exportEvent); }

 回到ReferenceAnnotationBeanPostProcessor

我们来看一下处理ReferenceAnnotationBeanPostProcessor.ServiceBeanExportEvent事件的方法

 

private void onServiceBeanExportEvent(ServiceBeanExportedEvent event) { ServiceBean serviceBean = event.getServiceBean(); initReferenceBeanInvocationHandler(serviceBean); }

跟进去

private void initReferenceBeanInvocationHandler(ServiceBean serviceBean) { String serviceBeanName = serviceBean.getBeanName(); // Remove ServiceBean when it's exported ReferenceBeanInvocationHandler handler = localReferenceBeanInvocationHandlerCache.remove(serviceBeanName); // Initialize if (handler != null) { handler.init(); } }

做了1件事:如果该serviceBean已经暴露exported,则从localReferenceBeanInvocationHandlerCache移除,且调用handler.init

那我debug的时候发现我的@Service修饰的服务提供者类在这里得到的handler==null,所以并没有走到Handler.init方法中去

 

最新回复(0)