Dubbo学习之监听器

相关阅读

  • Dubbo学习之自动配置
  • Dubbo学习之DubboConfigInitEvent
  • Dubbo学习之PostProcessor
  • Dubbo学习之DubboReference

简介

本文基于Spring Boot 2.6.6dubbo-spring-boot-starter 3.0.6环境。

Dubbo中使用的ApplicationListener如下:

  1. DubboConfigApplicationListener,实现了ApplicationListener
  2. DubboDeployApplicationListener,实现了ApplicationListener
  3. AwaitingNonWebApplicationListener,实现了SmartApplicationListener
  4. DubboConfigBeanDefinitionConflictApplicationListener,实现了ApplicationListener

引入时机

RootBeanDefinition注册时机

DubboConfigApplicationListenerDubboDeployApplicationListenerRootBeanDefinition注册时机在DubboBeanUtils.registerCommonBeans方法中,调用流程如下:

  1. DubboAutoConfiguration ->
  2. 由EnableDubboConfig引入DubboConfigConfigurationRegistrar ->
  3. DubboConfigConfigurationRegistrar.registerBeanDefinitions ->
  4. DubboSpringInitializer.initialize ->
  5. DubboSpringInitializer.initContext ->
  6. DubboBeanUtils.registerCommonBeans

DubboAutoConfiguration会被ConfigurationClassPostProcessor处理,解析其相关的RootBeanDefinition,调用流程如下:

  1. AbstractApplicationContext.refresh ->
  2. invokeBeanFactoryPostProcessors ->
  3. PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors ->
  4. … ->
  5. ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry ->
  6. ConfigurationClassPostProcessor.processConfigBeanDefinitions ->
  7. ConfigurationClassBeanDefinitionReader.loadBeanDefinitions

ConfigurationClassBeanDefinitionReader.loadBeanDefinitions方法中会执行DubboAutoConfiguration.importBeanDefinitionRegistrarsregisterBeanDefinitions来注册RootBeanDefinition
DubboAutoConfiguration.importBeanDefinitionRegistrars如下:

  1. EnableConfigurationPropertiesRegistrar,由EnableConfigurationProperties引入;
  2. DubboConfigConfigurationRegistrar,由EnableDubboConfig引入;

AwaitingNonWebApplicationListenerDubboConfigBeanDefinitionConflictApplicationListener是在DubboListenerAutoConfiguration中以BeanMethod形式定义,同DubboAutoConfiguration一样,DubboListenerAutoConfiguration也会被ConfigurationClassPostProcessor处理,最终由ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod方法将DubboListenerAutoConfiguration中所有的BeanMethod注册为RootBeanDefinition

Bean实例化时机

DubboConfigApplicationListener

DubboConfigApplicationListener实现了ApplicationListener,其关心的事件为DubboConfigInitEventDubboConfigApplicationListener是在DubboConfigInitEvent事件处理过程中被实例化,DubboConfigInitEvent事件是在ReferenceAnnotationBeanPostProcessor.postProcessBeanFactory中发布,所以DubboConfigApplicationListener的实例化主要涉及三个流程:

  1. 引入ReferenceAnnotationBeanPostProcessor
  2. 发布DubboConfigInitEvent
  3. 处理DubboConfigInitEvent

引入ReferenceAnnotationBeanPostProcessor

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法中,会执行容器中所有BeanFactoryPostProcessor的处理,执行顺序大致如下:

  1. 实现了PriorityOrderedBeanDefinitionRegistryPostProcessor
  2. 实现了OrderedBeanDefinitionRegistryPostProcessor
  3. 剩下的BeanDefinitionRegistryPostProcessor
  4. 实现了PriorityOrderedBeanFactoryPostProcessor
  5. 实现了OrderedBeanFactoryPostProcessor
  6. 剩下的BeanFactoryPostProcessor

注意:BeanFactoryPostProcessor的获取途径有两种:代码直接添加和配置(代码配置或者文件配置),这里分析的执行顺序没有考虑这两种途径的区别;

ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessorPriorityOrdered,所以它会先执行其postProcessBeanDefinitionRegistry逻辑,从而引入了DubboAutoConfiguration自动配置类,由上文可知,DubboAutoConfiguration自动配置会调用到DubboBeanUtils.registerCommonBeans,该方法内会注册ReferenceAnnotationBeanPostProcessorRootBeanDefinition
ReferenceAnnotationBeanPostProcessor实现了BeanFactoryPostProcessorOrdered,故在第五步时,会引入ReferenceAnnotationBeanPostProcessor并执行其postProcessBeanFactory方法;

发布DubboConfigInitEvent

ReferenceAnnotationBeanPostProcessor.postProcessBeanFactory方法中会发布DubboConfigInitEvent事件,代码如下:

applicationContext.publishEvent(new DubboConfigInitEvent(applicationContext));

此时,AbstractApplicationContext中还不存在ApplicationEventMulticaster,所以还无法真正发布事件,便先缓存到earlyApplicationEvents中,等初始化ApplicationEventMulticaster后再发布事件;
AbstractApplicationContext执行initApplicationEventMulticaster完成初始化ApplicationEventMulticaster后,便可以发布事件了,紧接着执行registerListeners,代码如下:

protected void registerListeners() {
    // 添加已存在的ApplicationListener
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 添加存在的ApplicationListener BeanName
    // 此时包含:
    // 1. org.apache.dubbo.config.spring.context.DubboDeployApplicationListener
    // 2. org.apache.dubbo.config.spring.context.DubboConfigApplicationListener
    // 3. dubboConfigBeanDefinitionConflictApplicationListener
    // 4. awaitingNonWebApplicationListener
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 发布缓存的早期事件
    // 此时包含DubboConfigInitEvent
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

处理DubboConfigInitEvent

ApplicationEventApplicationEventMulticaster.multicastEvent,默认实现为SimpleApplicationEventMulticaster,其代码如下:

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    Executor executor = getTaskExecutor();
    // 获取支持本事件的ApplicationListener
    // 支持DubboConfigInitEvent
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            invokeListener(listener, event);
        }
    }
}

获取支持指定事件的ApplicationListener过程中,如果已注册的BeanDefinition中存在匹配的ApplicationListener,那就将其实例化,核心代码如下:

private Collection<ApplicationListener<?>> retrieveApplicationListeners(
        ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable CachedListenerRetriever retriever) {

    List<ApplicationListener<?>> allListeners = new ArrayList<>();
    Set<ApplicationListener<?>> filteredListeners = (retriever != null ? new LinkedHashSet<>() : null);
    Set<String> filteredListenerBeans = (retriever != null ? new LinkedHashSet<>() : null);

    Set<ApplicationListener<?>> listeners;
    Set<String> listenerBeans;
    synchronized (this.defaultRetriever) {
        listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
        listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
    }

    // 先从已存在的ApplicationListener Bean中查找
    for (ApplicationListener<?> listener : listeners) {
        if (supportsEvent(listener, eventType, sourceType)) {
            if (retriever != null) {
                filteredListeners.add(listener);
            }
            allListeners.add(listener);
        }
    }

    // 再从ApplicationListener BeanDefinition中查找
    if (!listenerBeans.isEmpty()) {
        ConfigurableBeanFactory beanFactory = getBeanFactory();
        for (String listenerBeanName : listenerBeans) {
            try {
                if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
                    // 实例化该ApplicationListener
                    ApplicationListener<?> listener =
                            beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                    if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
                        if (retriever != null) {
                            if (beanFactory.isSingleton(listenerBeanName)) {
                                filteredListeners.add(listener);
                            }
                            else {
                                filteredListenerBeans.add(listenerBeanName);
                            }
                        }
                        allListeners.add(listener);
                    }
                }
                else {
                    Object listener = beanFactory.getSingleton(listenerBeanName);
                    if (retriever != null) {
                        filteredListeners.remove(listener);
                    }
                    allListeners.remove(listener);
                }
            }
            catch (NoSuchBeanDefinitionException ex) {
            }
        }
    }

    AnnotationAwareOrderComparator.sort(allListeners);
    if (retriever != null) {
        if (filteredListenerBeans.isEmpty()) {
            retriever.applicationListeners = new LinkedHashSet<>(allListeners);
            retriever.applicationListenerBeans = filteredListenerBeans;
        }
        else {
            // 更新信息,避免再次实例化ApplicationListener
            retriever.applicationListeners = filteredListeners;
            retriever.applicationListenerBeans = filteredListenerBeans;
        }
    }
    return allListeners;
}

在查找支持DubboConfigInitEventApplicationListener过程中,DubboConfigApplicationListener会被实例化;

DubboDeployApplicationListener

DubboDeployApplicationListener实现了ApplicationListener,其关心的事件为ContextRefreshedEventContextClosedEvent
其实例化时机是在AbstractApplicationContext.finishBeanFactoryInitialization,该方法会将容器中还未实例化的单例RootBeanDefinition预加载入容器中,即提前实例化;

AwaitingNonWebApplicationListener

AwaitingNonWebApplicationListener实现了SmartApplicationListener,其关心的事件为ApplicationReadyEventContextClosedEvent
AbstractApplicationEventMulticaster.retrieveApplicationListeners方法中判断SmartApplicationListener实现类是否支持指定事件,需先将其实例化,再根据其supportsEventType方法做进一步判断;
所以AwaitingNonWebApplicationListener实例化是在发生在处理第一次事件时,本文背景下,即为处理DubboConfigInitEvent事件时;

DubboConfigBeanDefinitionConflictApplicationListener

DubboConfigBeanDefinitionConflictApplicationListener实现了ApplicationListener,其关心的事件为ContextRefreshedEvent
其实例化时机是在AbstractApplicationContext.finishBeanFactoryInitialization,该方法会将容器中还未实例化的单例RootBeanDefinition预加载入容器中,即提前实例化;

监听逻辑

DubboConfigApplicationListener

DubboConfigApplicationListener只关心DubboConfigInitEvent,用于初始化Dubbo相关配置Bean,代码如下:

public void onApplicationEvent(DubboConfigInitEvent event) {
    if (nullSafeEquals(applicationContext, event.getSource())) {
        if (initialized.compareAndSet(false, true)) {
            // 如果已经初始化,则无需再次初始化
            initDubboConfigBeans();
        }
    }
}

initDubboConfigBeans方法将在下篇进行详细分析;

DubboDeployApplicationListener

DubboDeployApplicationListener关心ContextRefreshedEventContextClosedEvent,代码如下:

public void onApplicationEvent(ApplicationContextEvent event) {
    if (nullSafeEquals(applicationContext, event.getSource())) {
        if (event instanceof ContextRefreshedEvent) {
            onContextRefreshedEvent((ContextRefreshedEvent) event);
        } else if (event instanceof ContextClosedEvent) {
            onContextClosedEvent((ContextClosedEvent) event);
        }
    }
}

private void onContextRefreshedEvent(ContextRefreshedEvent event) {
    ModuleDeployer deployer = moduleModel.getDeployer();
    Assert.notNull(deployer, "Module deployer is null");
    // start module
    Future future = deployer.start();

    // if the module does not start in background, await finish
    if (!deployer.isBackground()) {
        try {
            future.get();
        } catch (InterruptedException e) {
            logger.warn("Interrupted while waiting for dubbo module start: " + e.getMessage());
        } catch (Exception e) {
            logger.warn("An error occurred while waiting for dubbo module start: " + e.getMessage(), e);
        }
    }
}

private void onContextClosedEvent(ContextClosedEvent event) {
    try {
        Object value = moduleModel.getAttribute(ModelConstants.KEEP_RUNNING_ON_SPRING_CLOSED);
        boolean keepRunningOnClosed = Boolean.parseBoolean(String.valueOf(value));
        if (!keepRunningOnClosed && !moduleModel.isDestroyed()) {
            moduleModel.destroy();
        }
    } catch (Exception e) {
        logger.error("An error occurred when stop dubbo module: " + e.getMessage(), e);
    }
    // remove context bind cache
    DubboSpringInitializer.remove(event.getApplicationContext());
}

AwaitingNonWebApplicationListener

AwaitingNonWebApplicationListener关心ApplicationReadyEventContextClosedEvent,代码如下:

public void onApplicationEvent(ApplicationEvent event) {
    if (event instanceof ApplicationReadyEvent) {
        onApplicationReadyEvent((ApplicationReadyEvent) event);
    }

    // 不支持ApplicationFailedEvent,应该无法走到
    if (event instanceof ApplicationFailedEvent) {
        awaitAndRelease(((ApplicationFailedEvent) event).getApplicationContext());
    }
}

protected void onApplicationReadyEvent(ApplicationReadyEvent event) {

    final ConfigurableApplicationContext applicationContext = event.getApplicationContext();

    if (!isRootApplicationContext(applicationContext) || isWebApplication(applicationContext)) {
        // WebApplicationContext或者ReactiveWebApplicationContext直接退出
        return;
    }

    if (applicationContextId.compareAndSet(UNDEFINED_ID, applicationContext.hashCode())) {
        awaitAndRelease(event.getApplicationContext());
    }
}

DubboConfigBeanDefinitionConflictApplicationListener

DubboConfigBeanDefinitionConflictApplicationListener只关心ContextRefreshedEvent,当系统启动成功后,会校验当前ApplicationConfig配置信息,代码如下:

public void onApplicationEvent(ContextRefreshedEvent event) {
    ApplicationContext applicationContext = event.getApplicationContext();
    BeanDefinitionRegistry registry = getBeanDefinitionRegistry(applicationContext);
    resolveUniqueApplicationConfigBean(registry, applicationContext);
}

private void resolveUniqueApplicationConfigBean(BeanDefinitionRegistry registry, ListableBeanFactory beanFactory) {

    // 从容器中获取ApplicationConfig类型的BeanName
    String[] beansNames = beanNamesForTypeIncludingAncestors(beanFactory, ApplicationConfig.class);

    if (beansNames.length < 2) {
        // 如果容器中只存在零个或一个ApplicationConfig,则无冲突直接退出
        return;
    }

    Environment environment = beanFactory.getBean(ENVIRONMENT_BEAN_NAME, Environment.class);

    // 移除由'dubbo.application.*'配置信息得到的BeanDefinition
    Stream.of(beansNames)
        .filter(beansName -> isConfiguredApplicationConfigBeanName(environment, beansName))
        .forEach(registry::removeBeanDefinition);

    // 再次从容器中获取ApplicationConfig类型的BeanName
    beansNames = beanNamesForTypeIncludingAncestors(beanFactory, ApplicationConfig.class);

    if (beansNames.length > 1) {
        // 如果容器中只存在不止一个ApplicationConfig,则抛出异常
        throw new IllegalStateException(String.format("There are more than one instances of %s, whose bean definitions : %s",
            ApplicationConfig.class.getSimpleName(),
            Stream.of(beansNames)
                .map(registry::getBeanDefinition)
                .collect(Collectors.toList()))
        );
    }
}

你可能感兴趣的:(Dubbo,dubbo)