事件发布
public void environmentPrepared(ConfigurableEnvironment environment) { for (SpringApplicationRunListener listener : this.listeners) { listener.environmentPrepared(environment); } }
private void publishEvent(SpringApplicationEvent event) { this.multicaster.multicastEvent(event); }
spring事件
@Override public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { invokeListener(listener, event); } }); } else { invokeListener(listener, event); } } }
通知listener
@SuppressWarnings({"unchecked", "rawtypes"}) protected void invokeListener(ApplicationListener listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { listener.onApplicationEvent(event); } catch (Throwable err) { errorHandler.handleError(err); } } else { try { listener.onApplicationEvent(event); } catch (ClassCastException ex) { // Possibly a lambda-defined listener which we could not resolve the generic event type for LogFactory.getLog(getClass()).debug("Non-matching event type for listener: " + listener, ex); } } }
大范围的观察者模式,初始是通过META-INF/spring.factories加载来的,还有通过容器注册的,还有refresh的时候注册进来的
# PropertySource Loaders org.springframework.boot.env.PropertySourceLoader= org.springframework.boot.env.PropertiesPropertySourceLoader, org.springframework.boot.env.YamlPropertySourceLoader # Run Listeners org.springframework.boot.SpringApplicationRunListener= org.springframework.boot.context.event.EventPublishingRunListener # Application Context Initializers org.springframework.context.ApplicationContextInitializer= org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer, org.springframework.boot.context.ContextIdApplicationContextInitializer, org.springframework.boot.context.config.DelegatingApplicationContextInitializer, org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer # Application Listeners org.springframework.context.ApplicationListener= org.springframework.boot.builder.ParentContextCloserApplicationListener, org.springframework.boot.context.FileEncodingApplicationListener, org.springframework.boot.context.config.AnsiOutputApplicationListener, org.springframework.boot.context.config.ConfigFileApplicationListener, org.springframework.boot.context.config.DelegatingApplicationListener, org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener, org.springframework.boot.logging.ClasspathLoggingApplicationListener, org.springframework.boot.logging.LoggingApplicationListener # Environment Post Processors org.springframework.boot.env.EnvironmentPostProcessor= org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor, org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor
通过后处理器添加
@Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (this.applicationContext != null && bean instanceof ApplicationListener) { // potentially not detected as a listener by getBeanNamesForType retrieval Boolean flag = this.singletonNames.get(beanName); if (Boolean.TRUE.equals(flag)) { // singleton bean (top-level or inner): register on the fly this.applicationContext.addApplicationListener((ApplicationListener<?>) bean); } else if (flag == null) { if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) { // inner bean with other scope - can't reliably process events logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " + "but is not reachable for event multicasting by its containing ApplicationContext " + "because it does not have singleton scope. Only top-level listener beans are allowed " + "to be of non-singleton scope."); } this.singletonNames.put(beanName, Boolean.FALSE); } } return bean; }