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

一、测试使用代码

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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值