一、测试使用代码
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监听了两个事件:ContextRefreshedEvent和ServiceBeanExportEvent
然而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方法中去