本文基于Spring Boot 2.6.6
,dubbo-spring-boot-starter 3.0.6
环境。
Dubbo中使用的ApplicationListener
如下:
DubboConfigApplicationListener
,实现了ApplicationListener
;DubboDeployApplicationListener
,实现了ApplicationListener
;AwaitingNonWebApplicationListener
,实现了SmartApplicationListener
;DubboConfigBeanDefinitionConflictApplicationListener
,实现了ApplicationListener
;DubboConfigApplicationListener
和DubboDeployApplicationListener
的RootBeanDefinition
注册时机在DubboBeanUtils.registerCommonBeans
方法中,调用流程如下:
DubboAutoConfiguration
->由EnableDubboConfig引入DubboConfigConfigurationRegistrar
->DubboConfigConfigurationRegistrar.registerBeanDefinitions
->DubboSpringInitializer.initialize
->DubboSpringInitializer.initContext
->DubboBeanUtils.registerCommonBeans
;DubboAutoConfiguration
会被ConfigurationClassPostProcessor
处理,解析其相关的RootBeanDefinition
,调用流程如下:
AbstractApplicationContext.refresh
->invokeBeanFactoryPostProcessors
->PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
->ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry
->ConfigurationClassPostProcessor.processConfigBeanDefinitions
->ConfigurationClassBeanDefinitionReader.loadBeanDefinitions
;ConfigurationClassBeanDefinitionReader.loadBeanDefinitions
方法中会执行DubboAutoConfiguration.importBeanDefinitionRegistrars
的registerBeanDefinitions
来注册RootBeanDefinition
;
DubboAutoConfiguration.importBeanDefinitionRegistrars
如下:
EnableConfigurationPropertiesRegistrar
,由EnableConfigurationProperties
引入;DubboConfigConfigurationRegistrar
,由EnableDubboConfig
引入;AwaitingNonWebApplicationListener
和DubboConfigBeanDefinitionConflictApplicationListener
是在DubboListenerAutoConfiguration
中以BeanMethod
形式定义,同DubboAutoConfiguration
一样,DubboListenerAutoConfiguration
也会被ConfigurationClassPostProcessor
处理,最终由ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod
方法将DubboListenerAutoConfiguration
中所有的BeanMethod
注册为RootBeanDefinition
;
DubboConfigApplicationListener
实现了ApplicationListener
,其关心的事件为DubboConfigInitEvent
;DubboConfigApplicationListener
是在DubboConfigInitEvent
事件处理过程中被实例化,DubboConfigInitEvent
事件是在ReferenceAnnotationBeanPostProcessor.postProcessBeanFactory
中发布,所以DubboConfigApplicationListener
的实例化主要涉及三个流程:
ReferenceAnnotationBeanPostProcessor
;DubboConfigInitEvent
;DubboConfigInitEvent
;在PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
方法中,会执行容器中所有BeanFactoryPostProcessor
的处理,执行顺序大致如下:
PriorityOrdered
的BeanDefinitionRegistryPostProcessor
;Ordered
的BeanDefinitionRegistryPostProcessor
;BeanDefinitionRegistryPostProcessor
;PriorityOrdered
的BeanFactoryPostProcessor
;Ordered
的BeanFactoryPostProcessor
;BeanFactoryPostProcessor
;注意:BeanFactoryPostProcessor
的获取途径有两种:代码直接添加和配置(代码配置或者文件配置),这里分析的执行顺序没有考虑这两种途径的区别;
ConfigurationClassPostProcessor
实现了BeanDefinitionRegistryPostProcessor
和PriorityOrdered
,所以它会先执行其postProcessBeanDefinitionRegistry
逻辑,从而引入了DubboAutoConfiguration
自动配置类,由上文可知,DubboAutoConfiguration
自动配置会调用到DubboBeanUtils.registerCommonBeans
,该方法内会注册ReferenceAnnotationBeanPostProcessor
的RootBeanDefinition
;
ReferenceAnnotationBeanPostProcessor
实现了BeanFactoryPostProcessor
和Ordered
,故在第五步时,会引入ReferenceAnnotationBeanPostProcessor
并执行其postProcessBeanFactory
方法;
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);
}
}
}
ApplicationEvent
由ApplicationEventMulticaster.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;
}
在查找支持DubboConfigInitEvent
的ApplicationListener
过程中,DubboConfigApplicationListener
会被实例化;
DubboDeployApplicationListener
实现了ApplicationListener
,其关心的事件为ContextRefreshedEvent
和ContextClosedEvent
;
其实例化时机是在AbstractApplicationContext.finishBeanFactoryInitialization
,该方法会将容器中还未实例化的单例RootBeanDefinition
预加载入容器中,即提前实例化;
AwaitingNonWebApplicationListener
实现了SmartApplicationListener
,其关心的事件为ApplicationReadyEvent
和ContextClosedEvent
;
在AbstractApplicationEventMulticaster.retrieveApplicationListeners
方法中判断SmartApplicationListener
实现类是否支持指定事件,需先将其实例化,再根据其supportsEventType
方法做进一步判断;
所以AwaitingNonWebApplicationListener
实例化是在发生在处理第一次事件时,本文背景下,即为处理DubboConfigInitEvent
事件时;
DubboConfigBeanDefinitionConflictApplicationListener
实现了ApplicationListener
,其关心的事件为ContextRefreshedEvent
;
其实例化时机是在AbstractApplicationContext.finishBeanFactoryInitialization
,该方法会将容器中还未实例化的单例RootBeanDefinition
预加载入容器中,即提前实例化;
DubboConfigApplicationListener
只关心DubboConfigInitEvent
,用于初始化Dubbo相关配置Bean,代码如下:
public void onApplicationEvent(DubboConfigInitEvent event) {
if (nullSafeEquals(applicationContext, event.getSource())) {
if (initialized.compareAndSet(false, true)) {
// 如果已经初始化,则无需再次初始化
initDubboConfigBeans();
}
}
}
initDubboConfigBeans
方法将在下篇进行详细分析;
DubboDeployApplicationListener
关心ContextRefreshedEvent
和ContextClosedEvent
,代码如下:
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
关心ApplicationReadyEvent
和ContextClosedEvent
,代码如下:
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
只关心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()))
);
}
}