spring-cloud-starter-dubbo启动过程

一、 DubboAutoConfiguration


@ConditionalOnProperty(
    prefix = "dubbo",
    name = {"enabled"},
    matchIfMissing = true
)
@Configuration
@AutoConfigureAfter({DubboRelaxedBindingAutoConfiguration.class})
@EnableConfigurationProperties({DubboConfigurationProperties.class})
@EnableDubboConfig
public class DubboAutoConfiguration implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor {
    public DubboAutoConfiguration() {
    }

    @ConditionalOnProperty(
        prefix = "dubbo.scan.",
        name = {"base-packages"}
    )
    @ConditionalOnBean(
        name = {"dubbo-service-class-base-packages"}
    )
    @Bean
    public ServiceClassPostProcessor serviceClassPostProcessor(@Qualifier("dubbo-service-class-base-packages") Set<String> packagesToScan) {
        return new ServiceClassPostProcessor(packagesToScan);
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (applicationContext instanceof ConfigurableApplicationContext) {
            ConfigurableApplicationContext context = (ConfigurableApplicationContext)applicationContext;
            DubboLifecycleComponentApplicationListener dubboLifecycleComponentApplicationListener = new DubboLifecycleComponentApplicationListener();
            dubboLifecycleComponentApplicationListener.setApplicationContext(applicationContext);
            context.addApplicationListener(dubboLifecycleComponentApplicationListener);
            DubboBootstrapApplicationListener dubboBootstrapApplicationListener = new DubboBootstrapApplicationListener();
            dubboBootstrapApplicationListener.setApplicationContext(applicationContext);
            context.addApplicationListener(dubboBootstrapApplicationListener);
        }

    }

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        this.removeBeanDefinition(registry, "dubboLifecycleComponentApplicationListener");
        this.removeBeanDefinition(registry, "dubboBootstrapApplicationListener");
    }

    private void removeBeanDefinition(BeanDefinitionRegistry registry, String beanName) {
        if (registry.containsBeanDefinition(beanName)) {
            registry.removeBeanDefinition(beanName);
        }

    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }
}

这是dubbo-spring-boot-starter.jar中主要的启动配置类,该类直接通过@Bean注册ServiceClassPostProcessor到Spring容器中,并通过**@EnableDubboConfig引入DubboConfigConfigurationRegistrar**,注册ReferenceAnnotationBeanPostProcessor、DubboConfigAliasPostProcessor、DubboLifecycleComponentApplicationListener、DubboBootstrapApplicationListener和DubboConfigDefaultPropertyValueBeanPostProcessor到Spring容器中。

  • DubboConfigDefaultPropertyValueBeanPostProcessor:用来填充AbstarctConfig.id和AbstarctConfig.name的默认值
  • DubboConfigAliasPostProcessor:用来注册beanName和AbstarctConfig.id的别名
  • DubboLifecycleComponentApplicationListener:用来从Spring容器中获取所有实现了org.apache.dubbo.common.context.LifeCycle接口的Bean,并执行他们的start()方法;
  • ServiceClassPostProcessor:扫描所有@DubboService注解的类,构建成ServiceBean注册到Srping容器中;
  • ReferenceAnnotationBeanPostProcessor:扫描Bean中所有@DubboReference注解的属性,通过ReferenceBean构建远程服务的实例,注入到相应的依赖中;
  • DubboBootstrapApplicationListener:监听ContextRefreshedEvent和ContextClosedEvent事件,相应的执行DubboBootstrap的start()和stop()方法;

下面会详细介绍ServiceClassPostProcessor、ReferenceAnnotationBeanPostProcessor和DubboBootstrapApplicationListener的作用。

二、ServiceClassPostProcessor

该类的主要作用是将@DubboService和@org.apache.dubbo.config.annotation.Service注释的类注册到Spring容器中。

1、UML类图:

![image.png](https://img-blog.csdnimg.cn/img_convert/552634287af5a85fa577fa7e3d823a22.png#crop=0&crop=0&crop=1&crop=1&height=627&id=SZvqg&margin=[object Object]&name=image.png&originHeight=627&originWidth=1328&originalType=binary&ratio=1&rotation=0&showTitle=false&size=41560&status=done&style=none&title=&width=1328)
EnvironmentAware,ResourceLoaderAware,BeanClassLoaderAware全部继承自Aware接口,用于set对应的bean到对象中。
BeanDefinitionRegistryPostProcessor:可以通过此接口传入的BeanDefinitionRegistry注册Bean到Spring容器中,或判断Spring容器是否存在某个Bean,或从Spring容器中删除某个bean;

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

关于BeanDefinitionRegistryPostProcessor详细的介绍可以参考:https://blog.csdn.net/ztchun/article/details/90814135

2、 支持的注解:DubboService、org.apache.dubbo.config.annotation.Service,com.alibaba.dubbo.config.annotation.Service

private final static List<Class<? extends Annotation>> serviceAnnotationTypes = asList(
    // @since 2.7.7 Add the @DubboService , the issue : https://github.com/apache/dubbo/issues/6007
    DubboService.class,
    // @since 2.7.0 the substitute @com.alibaba.dubbo.config.annotation.Service
    Service.class,
    // @since 2.7.3 Add the compatibility for legacy Dubbo's @Service , the issue : https://github.com/apache/dubbo/issues/4330
    com.alibaba.dubbo.config.annotation.Service.class
);

3、方法:postProcessBeanDefinitionRegistry

@Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        // @since 2.7.5
        //这里重复注册了一次DubboBootstrapApplicationListener
        registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class);

        Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);

        if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
            registerServiceBeans(resolvedPackagesToScan, registry);
        } else {
            if (logger.isWarnEnabled()) {
                logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
            }
        }

    }

此方法实现自接口BeanDefinitionRegistryPostProcessor:
该方法首先注册DubboBootstrapApplicationListener到Spring容器,DubboBootstrapApplicationListener用来监听ContextRefreshedEvent,Spring Context刷新完成后,调用DubboBootstrap.start()方法,启动Dubbo服务;
然后解析要扫描的报列表,从${dubbo.scan.base-packages}配置项读取扫描列表,如果扫描列表不为空,则调用registerServiceBeans方法;

4、 方法:registerServiceBeans

private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {

        DubboClassPathBeanDefinitionScanner scanner =
                new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);

        BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);

        scanner.setBeanNameGenerator(beanNameGenerator);

        // refactor @since 2.7.7
        serviceAnnotationTypes.forEach(annotationType -> {
            scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
        });

        for (String packageToScan : packagesToScan) {

            // Registers @Service Bean first
            scanner.scan(packageToScan);

            // Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
            Set<BeanDefinitionHolder> beanDefinitionHolders =
                    findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);

            if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {

                for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                    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 + "]");
                }

            }

        }

    }

使用DubboClassPathBeanDefinitionScanner扫描所有的DubboService类,然后遍历扫描结果,调用registerServiceBean方法,注册bean到Spring容器中。

5、方法:registerServiceBean

private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
                                     DubboClassPathBeanDefinitionScanner scanner) {
		
    //从BeanDefinitionHolder解析出beanClass;
    Class<?> beanClass = resolveClass(beanDefinitionHolder);
	
    //按顺序从beanClass获取@DubboService、@org.apache.dubbo.config.annotation.Service或@com.alibaba.dubbo.config.annotation.Service注解
    Annotation service = findServiceAnnotation(beanClass);

    /**
     * The {@link AnnotationAttributes} of @Service annotation
     */
    //从注解从读取属性值,用于后续构建Dubbo Service Bean时的参数;
    AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);
	
    //获取DubboService的接口类,如果注解中指定了接口类,则使用注解中指定的类(解析顺序interfaceClass->interfaceName),否则使用服务类实现的接口中的第一个。如果找不到接口类,则抛出异常;
    Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);

    
    String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();

    //构建ServiceBean
    AbstractBeanDefinition serviceBeanDefinition =
        buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);

    // ServiceBean Bean name
    //使用ServiceBeanNameBuilder生成beanName
    String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);

    //检查是否可以注册到容器中
    if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
        //注册ServiceBean到容器中
        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?");
        }

    }

}

6、方法:buildServiceBeanDefinition

private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnnotation,
                                                          AnnotationAttributes serviceAnnotationAttributes,
                                                          Class<?> interfaceClass,
                                                          String annotatedServiceBeanName) {
	//创建 ServiceBean BeanDefinitionBuilder
    BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);

    AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

    MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();

    String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol",
                                       "interface", "interfaceName", "parameters");
    
	//从Annotation读取属性并设置到MutablePropertyValues中,比如group,version
    propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotation, environment, ignoreAttributeNames));
	
    // References "ref" property to annotated-@Service Bean
    addPropertyReference(builder, "ref", annotatedServiceBeanName);
    // Set interface
    builder.addPropertyValue("interface", interfaceClass.getName());
    // Convert parameters into map
    builder.addPropertyValue("parameters", convertParameters(serviceAnnotationAttributes.getStringArray("parameters")));
    // Add methods parameters
    List<MethodConfig> methodConfigs = convertMethodConfigs(serviceAnnotationAttributes.get("methods"));
    if (!methodConfigs.isEmpty()) {
        builder.addPropertyValue("methods", methodConfigs);
    }

    /**
     * Add {@link org.apache.dubbo.config.ProviderConfig} Bean reference
     */
    String providerConfigBeanName = serviceAnnotationAttributes.getString("provider");
    if (StringUtils.hasText(providerConfigBeanName)) {
        addPropertyReference(builder, "provider", providerConfigBeanName);
    }

    /**
         * Add {@link org.apache.dubbo.config.MonitorConfig} Bean reference
         */
    String monitorConfigBeanName = serviceAnnotationAttributes.getString("monitor");
    if (StringUtils.hasText(monitorConfigBeanName)) {
        addPropertyReference(builder, "monitor", monitorConfigBeanName);
    }

    /**
         * Add {@link org.apache.dubbo.config.ApplicationConfig} Bean reference
         */
    String applicationConfigBeanName = serviceAnnotationAttributes.getString("application");
    if (StringUtils.hasText(applicationConfigBeanName)) {
        addPropertyReference(builder, "application", applicationConfigBeanName);
    }

    /**
     * Add {@link org.apache.dubbo.config.ModuleConfig} Bean reference
     */
    String moduleConfigBeanName = serviceAnnotationAttributes.getString("module");
    if (StringUtils.hasText(moduleConfigBeanName)) {
        addPropertyReference(builder, "module", moduleConfigBeanName);
    }


    /**
     * Add {@link org.apache.dubbo.config.RegistryConfig} Bean reference
     */
    String[] registryConfigBeanNames = serviceAnnotationAttributes.getStringArray("registry");

    List<RuntimeBeanReference> registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames);

    if (!registryRuntimeBeanReferences.isEmpty()) {
        builder.addPropertyValue("registries", registryRuntimeBeanReferences);
    }

    /**
     * Add {@link org.apache.dubbo.config.ProtocolConfig} Bean reference
     */
    String[] protocolConfigBeanNames = serviceAnnotationAttributes.getStringArray("protocol");

    List<RuntimeBeanReference> protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);

    if (!protocolRuntimeBeanReferences.isEmpty()) {
        builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
    }

    return builder.getBeanDefinition();

}

三、 ServiceBean

Dubbo服务的定义类,用于封装Dubbo服务的参数,如group、version、interfaceClass,服务类对象实例等,我们可以通过自定义ServiceBean来自定义需要发布的Dubbo服务,如:

@Bean
public ServiceBean<DubboMappingService> dubboDefinitionServiceBean(DubboMappingService dubboDefinitionService){
    ServiceBean<DubboMappingService> serviceBean = new ServiceBean<>();
    serviceBean.setVersion(CommonServiceVersion.DUBBO_DEFINITION_SERVICE);//版本
    serviceBean.setGroup(this.applicationName);//将Dubbo服务的group设置为application Name
    serviceBean.setRef(dubboDefinitionService);//实现类对象实例
    serviceBean.setInterface(DubboMappingService.class);//接口类
    return serviceBean;
}

需要重点关注的方法:export()和addIntoConfigManager(),后面会详细介绍

1、UML类图
![image.png](https://img-blog.csdnimg.cn/img_convert/0793b437ac37497a40c6a805e88e2d02.png#crop=0&crop=0&crop=1&crop=1&height=1145&id=oEl8h&margin=[object Object]&name=image.png&originHeight=1145&originWidth=1658&originalType=binary&ratio=1&rotation=0&showTitle=false&size=84133&status=done&style=none&title=&width=1658)

  • ServiceConfig:用于Dubbo服务暴漏
  • **InitializingBean **, 主要是用到了他的afterPropertiesSet方法,在对象实例化完毕后,调用该方法,做一些值的初始化
  • **DisposableBean **, 主要用到他的destroy() 方法, 在spring容器showdown的时候调用。
  • ApplicationContextAware, 为了得到applicationContext
  • ApplicationEventPublisherAware, 用于发布ServiceBeanExportedEvent,DubboMetadataAutoConfiguration中会监听此事件,发布RestMetadata;
  • **BeanNameAware **, 用于设置Bean的名称

2、 方法:addIntoConfigManager():继承自AbstractConfig

@PostConstruct
public void addIntoConfigManager() {
    ApplicationModel.getConfigManager().addConfig(this);
}

@PostConstruct:java原生注解,用于在执行构造函数后,init()前执行的方法,在Spring框架中@PostConstruct执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
addIntoConfigManager():用于将ServiceBean注册到Dubbo的ConfigManager中,用于后续在DubboBootstrap.start()方法中暴露到注册中心。

3、 方法:export():继承自ServiceConfig

public synchronized void export() {
    if (!shouldExport()) {
        return;
    }

    if (bootstrap == null) {
        bootstrap = DubboBootstrap.getInstance();
        bootstrap.initialize();
    }

    checkAndUpdateSubConfigs();

    //init serviceMetadata
    serviceMetadata.setVersion(getVersion());
    serviceMetadata.setGroup(getGroup());
    serviceMetadata.setDefaultGroup(getGroup());
    serviceMetadata.setServiceType(getInterfaceClass());
    serviceMetadata.setServiceInterfaceName(getInterface());
    serviceMetadata.setTarget(getRef());

    if (shouldDelay()) {
        DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS);
    } else {
        doExport();
    }

    exported();
}

用户暴露服务到注册中心,该方法在DubboBootstrap.exportServices()中被调用。

三、 ReferenceAnnotationBeanPostProcessor

自动注入@DubboReference和@org.apache.dubbo.config.annotation.Reference注解注释的属性

1、UML类图:

![image.png](https://img-blog.csdnimg.cn/img_convert/79c47cfdfa338cd0ed19f3c62b037fe2.png#crop=0&crop=0&crop=1&crop=1&height=683&id=Go0PT&margin=[object Object]&name=image.png&originHeight=683&originWidth=1868&originalType=binary&ratio=1&rotation=0&showTitle=false&size=74239&status=done&style=none&title=&width=1868)
PriorityOrdered: 继承自Ordered接口,Spring OrderComparator会有限使用此接口的值进行对比排序;
BeanFactoryAware:设置BeanFactory
BeanClassLoaderAware:设置ClassLoader
EnvironmentAware:设置Environment
ApplicationContextAware:设置ApplicationContext
DisposableBean:主要用到他的destroy() 方法, 在spring容器showdown的时候调用。
MergedBeanDefinitionPostProcessor:依赖注入检查。
InstantiationAwareBeanPostProcessorAdapter:实现了postProcessPropertyValues接口,用于注入依赖;

2、方法:postProcessMergedBeanDefinition

实现自接口MergedBeanDefinitionPostProcessor,在AbstractAutowireCapableBeanFactory中调用:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof MergedBeanDefinitionPostProcessor) {
            MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
            bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
    }
}

接口实现代码:

 @Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    if (beanType != null) {
        InjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
        metadata.checkConfigMembers(beanDefinition);
    }
}

3、postProcessPropertyValues

接口实现代码:

@Override
public PropertyValues postProcessPropertyValues(
    PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

    InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
    try {
        metadata.inject(bean, beanName, pvs);
    } catch (BeanCreationException ex) {
        throw ex;
    } catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName()
                                        + " dependencies is failed", ex);
    }
    return pvs;
}

4、findInjectionMetadata

扫描所有@DubboReference和@org.apache.dubbo.config.annotation.Reference注释的Field,生成

private InjectionMetadata findInjectionMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // Quick check on the concurrent map first, with minimal locking.
    AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                try {
                    //扫描calzz中所有@DubboReference和@org.apache.dubbo.config.annotation.Reference注释的属性,并构建AnnotatedFieldElement
                    metadata = buildAnnotatedMetadata(clazz);
                    this.injectionMetadataCache.put(cacheKey, metadata);
                } catch (NoClassDefFoundError err) {
                    throw new IllegalStateException("Failed to introspect object class [" + clazz.getName() +
                                                    "] for annotation metadata: could not find class that it depends on", err);
                }
            }
        }
    }
    return metadata;
}

5、AnnotatedFieldElement.inject:继承自InjectionMetadata.InjectedElement

在InstantiationAwareBeanPostProcessor.postProcessPropertyValues方法中被调用,调用Field.set方法,注入依赖

@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {

    Class<?> injectedType = resolveInjectedType(bean, field);

    //获取要注入的对象,先从缓存中取,如果取不到,调用doGetInjectedBean方法构建;
    Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);

    ReflectionUtils.makeAccessible(field);

    field.set(bean, injectedObject);

}

6、doGetInjectedBean

@Override
protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                   InjectionMetadata.InjectedElement injectedElement) throws Exception {
    /**
         * The name of bean that annotated Dubbo's {@link Service @Service} in local Spring {@link ApplicationContext}
         */
    String referencedBeanName = buildReferencedBeanName(attributes, injectedType);

    /**
         * The name of bean that is declared by {@link Reference @Reference} annotation injection
         */
    String referenceBeanName = getReferenceBeanName(attributes, injectedType);

    ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);

    boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);

    prepareReferenceBean(referencedBeanName, referenceBean, localServiceBean);

    registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);

    cacheInjectedReferenceBean(referenceBean, injectedElement);

    return referenceBean.get();
}

构建ReferenceBean,继承自ReferenceConfig,我们常用ReferenceConfig进行Dubbo服务的泛化调用;

四、 ReferenceBean

1、UML类图

![image.png](https://img-blog.csdnimg.cn/img_convert/e1562daecc601ac80a8016236d6db30f.png#crop=0&crop=0&crop=1&crop=1&height=1136&id=Wb8ur&margin=[object Object]&name=image.png&originHeight=1136&originWidth=1279&originalType=binary&ratio=1&rotation=0&showTitle=false&size=69728&status=done&style=none&title=&width=1279)
ReferenceBean也继承自AbstractConfig,同样会通过addIntoConfigManager()方法将自身注册导ConfigManager中,以便在DubboBootstrap调用referenceConfig.get()方法;

五、 DubboBootstrapApplicationListener

实现了ApplicationListener接口,监听ContextRefreshedEvent和ContextClosedEvent事件;

1、构建方法:

public DubboBootstrapApplicationListener() {
    this.dubboBootstrap = DubboBootstrap.getInstance();
}

2、onContextRefreshedEvent

private void onContextRefreshedEvent(ContextRefreshedEvent event) {
    dubboBootstrap.start();
}

3、onContextClosedEvent

private void onContextClosedEvent(ContextClosedEvent event) {
    dubboBootstrap.stop();
}

六、DubboBootstrap:Dubbo的核心类,单例模式

1、initialize:初始化dubbo的环境配置,

public void initialize() {
    if (!initialized.compareAndSet(false, true)) {
        确保只执行一次
        return;
    }

    ApplicationModel.initFrameworkExts();

    startConfigCenter();

    loadRemoteConfigs();

    checkGlobalConfigs();

    // @since 2.7.8
    startMetadataCenter();

    initMetadataService();

    initMetadataServiceExports();

    initEventListener();

    if (logger.isInfoEnabled()) {
        logger.info(NAME + " has been initialized!");
    }
}

2、start:dubbo服务启动,主要从ConfigManager中获取ServiceConfig和ReferenceConfig,暴漏自身服务,并解析远程服务;

public DubboBootstrap start() {
    if (started.compareAndSet(false, true)) {
        ready.set(false);
        initialize();
        if (logger.isInfoEnabled()) {
            logger.info(NAME + " is starting...");
        }
        // 1. export Dubbo Services
        exportServices();

        // Not only provider register
        if (!isOnlyRegisterProvider() || hasExportedServices()) {
            // 2. export MetadataService
            exportMetadataService();
            //3. Register the local ServiceInstance if required
            registerServiceInstance();
        }
		// reference dubbo remote service
        referServices();
        if (asyncExportingFutures.size() > 0) {
            new Thread(() -> {
                try {
                    this.awaitFinish();
                } catch (Exception e) {
                    logger.warn(NAME + " exportAsync occurred an exception.");
                }
                ready.set(true);
                if (logger.isInfoEnabled()) {
                    logger.info(NAME + " is ready.");
                }
            }).start();
        } else {
            ready.set(true);
            if (logger.isInfoEnabled()) {
                logger.info(NAME + " is ready.");
            }
        }
        if (logger.isInfoEnabled()) {
            logger.info(NAME + " has started.");
        }
    }
    return this;
}

3、stop: Dubbo停止服务,调用destroy()方法,销毁相关实例。

public void destroy() {
    if (destroyLock.tryLock()) {
        try {
            DubboShutdownHook.destroyAll();

            if (started.compareAndSet(true, false)
                && destroyed.compareAndSet(false, true)) {

                unregisterServiceInstance();
                unexportMetadataService();
                unexportServices();
                unreferServices();

                destroyRegistries();
                DubboShutdownHook.destroyProtocols();
                destroyServiceDiscoveries();

                clear();
                shutdown();
                release();
            }
        } finally {
            destroyLock.unlock();
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值