SpringBoot源码分析之-启动流程分析三(监听器SpringApplicationRunListener)

前言

上一篇SpringBoot源码分析之-启动流程分析二(run方法)简单分析了的run流程
这一篇主要分析一下监听器 SpringApplicationRunListener

观察者模式

	class SpringApplicationRunListeners {
		//监听器集合
		private final List<SpringApplicationRunListener> listeners;
		SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
			this.log = log;
			this.listeners = new ArrayList<>(listeners);
		}
		
		void starting() {
			for (SpringApplicationRunListener listener : this.listeners) {
				listener.starting();
			}
		}
		//其他方法差不多就是处理同的事件
		...
	}

	public interface SpringApplicationRunListener {
		default void starting() {}
		default void environmentPrepared(ConfigurableEnvironment environment) {}
		default void contextPrepared(ConfigurableApplicationContext context) {}
		default void contextLoaded(ConfigurableApplicationContext context) {}
		default void started(ConfigurableApplicationContext context) {}
		default void running(ConfigurableApplicationContext context) {}
		default void failed(ConfigurableApplicationContext context, Throwable exception) {}
	}
//---EventPublishingRunListener 方法对应的事件
starting: ApplicationStartingEvent
environmentPrepared: ApplicationEnvironmentPreparedEvent
contextPrepared: ApplicationContextInitializedEvent
contextLoaded: ApplicationPreparedEvent
started: ApplicationStartedEvent
running: ApplicationReadyEvent
failed: ApplicationFailedEvent

这个比较好看出是用了观察者模式
SpringApplicationRunListeners 中维护了SpringApplicationRunListener集合,
ApplicationEvent广播SpringApplicationRunListener处理相应的事件

run方法中出现的地方

		//获取监听器
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//广播 ApplicationStartingEvent
		listeners.starting();
		//准备环境
		ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
		//准备上下文 
		prepareContext(context, environment, listeners, applicationArguments, printedBanner);
		//广播容器启动成功
		listeners.started(context);
		//广播容器运行
		listeners.running(context);
		//还有一个catch中的失败广播
		handleRunFailure(context, ex, exceptionReporters, listeners);

1.获取监听器

private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
	}

getSpringFactoriesInstances方法之前分析过就是从类路径下的所有META-INF/spring.factories中去获取对应的实现类 ,这里是SpringApplicationRunListener对应实现类实例
这里目前一个实现类org.springframework.boot.context.event.EventPublishingRunListener

2. starting()

	void starting() {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.starting();
		}
	}
	
	@Override
	public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}

    //SimpleApplicationEventMulticaster
	@Override
	public void multicastEvent(ApplicationEvent event) {
		multicastEvent(event, resolveDefaultEventType(event));
	}

	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		//现在是null
		Executor executor = getTaskExecutor();
		//getApplicationListeners根据是否支持事件过滤SpringApplication设置的监听器
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}
	protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
		//==null
		ErrorHandler errorHandler = getErrorHandler();
		if (errorHandler != null) {
			try {
				doInvokeListener(listener, event);
			}
			catch (Throwable err) {
				errorHandler.handleError(err);
			}
		}
		else {
			doInvokeListener(listener, event);
		}
	}
	
	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
			//对应的监听器执行方法
			listener.onApplicationEvent(event);
		}
	......
	}
listener.onApplicationEvent(event);就是对应监听器处理事件的方法

好了到此SpringApplicationRunListener处理事件大致流程分析清楚了.其他细节有兴趣可以看下.
下一篇准备分析 prepareEnvironment环境准备.

getApplicationListeners() 筛选出支持该事件的监听器监听器

//public abstract class AbstractApplicationEventMulticaster
//		implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
protected Collection<ApplicationListener<?>> getApplicationListeners(
			ApplicationEvent event, ResolvableType eventType) {

		Object source = event.getSource();
		Class<?> sourceType = (source != null ? source.getClass() : null);
		ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

		// Quick check for existing entry on ConcurrentHashMap...
		ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
		if (retriever != null) {
			return retriever.getApplicationListeners();
		}

		if (this.beanClassLoader == null ||
				(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
						(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
			// Fully synchronized building and caching of a ListenerRetriever
			synchronized (this.retrievalMutex) {
				retriever = this.retrieverCache.get(cacheKey);
				if (retriever != null) {
					return retriever.getApplicationListeners();
				}
				retriever = new ListenerRetriever(true);
				//来看这行  筛选监听器逻辑
				Collection<ApplicationListener<?>> listeners =
						retrieveApplicationListeners(eventType, sourceType, retriever);
				this.retrieverCache.put(cacheKey, retriever);
				return listeners;
			}
		}
		else {
			// No ListenerRetriever caching -> no synchronization necessary
			return retrieveApplicationListeners(eventType, sourceType, null);
		}
	}


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

		List<ApplicationListener<?>> allListeners = new ArrayList<>();
		Set<ApplicationListener<?>> listeners;
		Set<String> listenerBeans;
		synchronized (this.retrievalMutex) {
			//初始化时设置的监听器集合
			listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
			listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
		}

		// Add programmatically registered listeners, including ones coming
		// from ApplicationListenerDetector (singleton beans and inner beans).
		for (ApplicationListener<?> listener : listeners) {
			if (supportsEvent(listener, eventType, sourceType)) {
				if (retriever != null) {
					retriever.applicationListeners.add(listener);
				}
				allListeners.add(listener);
			}
		}
.... //下面是有bean情况下的逻辑, 现在还没到容器初始化
	protected boolean supportsEvent(
			ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {

		GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
				(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
		return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
	}

这里有个适配器模式,还是比较好看出的
GenericApplicationListener 和 GenericApplicationListenerAdapter
如果监听器没有实现GenericApplicationListener 就创建一个GenericApplicationListenerAdapter适配器
主要supportsEventType 和 supportsSourceType两个方法确认监听器是否符合事件

//GenericApplicationListener接口
	boolean supportsEventType(ResolvableType eventType);

	/**
	 * Determine whether this listener actually supports the given source type.
	 * <p>The default implementation always returns {@code true}.
	 * @param sourceType the source type, or {@code null} if no source
	 */
	default boolean supportsSourceType(@Nullable Class<?> sourceType) {
		return true;
	}



//-----下面是GenericApplicationListenerAdapter类
	private final ApplicationListener<ApplicationEvent> delegate;
	@Nullable
	private final ResolvableType declaredEventType;
	
	public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
		Assert.notNull(delegate, "Delegate listener must not be null");
		this.delegate = (ApplicationListener<ApplicationEvent>) delegate;
		this.declaredEventType = resolveDeclaredEventType(this.delegate);
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public boolean supportsEventType(ResolvableType eventType) {
		if (this.delegate instanceof SmartApplicationListener) {
			Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
			return (eventClass != null && ((SmartApplicationListener) this.delegate).supportsEventType(eventClass));
		}
		else {
			return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));
		}
	}

	@Override
	public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
		return supportsEventType(ResolvableType.forClass(eventType));
	}

根据是否支持事件类型和源来过滤出监听器
举个例子:LoggingApplicationListener

public class LoggingApplicationListener implements GenericApplicationListener {

	private static final Class<?>[] EVENT_TYPES = { ApplicationStartingEvent.class,
			ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class, ContextClosedEvent.class,
			ApplicationFailedEvent.class };
			
	private static final Class<?>[] SOURCE_TYPES = { SpringApplication.class, ApplicationContext.class };

	@Override
	public boolean supportsEventType(ResolvableType resolvableType) {
		return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);
	}

	@Override
	public boolean supportsSourceType(Class<?> sourceType) {
		return isAssignableFrom(sourceType, SOURCE_TYPES);
	}
}

可以看到LoggingApplicationListener 支持的类型EVENT_TYPES 和 源类型SOURCE_TYPES

所以根据事件类型和源过滤了获取了4个类
(第一篇构造SpringApplication中获取的监听器中过滤)

0 = {CloudFoundryVcapEnvironmentPostProcessor@1725} 
1 = {ConfigFileApplicationListener@1726} 
2 = {AnsiOutputApplicationListener@1727} 
3 = {LoggingApplicationListener@1728} 
4 = {ClasspathLoggingApplicationListener@1729} 
5 = {BackgroundPreinitializer@1730} 
6 = {DelegatingApplicationListener@1731} 
7 = {ParentContextCloserApplicationListener@1732} 
8 = {ClearCachesApplicationListener@1733} 
9 = {FileEncodingApplicationListener@1734} 
10 = {LiquibaseServiceLocatorApplicationListener@1735} 

//---

LoggingApplicationListener
BackgroundPreinitializer
DelegatingApplicationListener
LiquibaseServiceLocatorApplicationListener

**listener.onApplicationEvent(event);**监听器执行自己的方法了
这里就 LoggingApplicationListener 和 BackgroundPreinitializer 有对ApplicationStartingEvent事件类型的处理
LoggingApplicationListener 设置了日志系统 这里默认是Logback

Map<String, String> systems = new LinkedHashMap<>();
		systems.put("ch.qos.logback.core.Appender", "org.springframework.boot.logging.logback.LogbackLoggingSystem");
		systems.put("org.apache.logging.log4j.core.impl.Log4jContextFactory",
				"org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");
		systems.put("java.util.logging.LogManager", "org.springframework.boot.logging.java.JavaLoggingSystem");
		SYSTEMS = Collections.unmodifiableMap(systems);

BackgroundPreinitializer 起了一个线程执行以下操作 一些工具的初始化
ApplicationReadyEvent 和 ApplicationFailedEvent 也就是后续的这两个事件会等他执行完

	public void onApplicationEvent(SpringApplicationEvent event) {
		if (!Boolean.getBoolean(IGNORE_BACKGROUNDPREINITIALIZER_PROPERTY_NAME)
				&& event instanceof ApplicationStartingEvent && multipleProcessors()
				&& preinitializationStarted.compareAndSet(false, true)) {
			performPreinitialization();
		}
		if ((event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent)
				&& preinitializationStarted.get()) {
			try {
				preinitializationComplete.await();
			}
			catch (InterruptedException ex) {
				Thread.currentThread().interrupt();
			}
		}
	}
	// performPreinitialization() 
	public void run() {
			runSafely(new ConversionServiceInitializer());
			runSafely(new ValidationInitializer());
			runSafely(new MessageConverterInitializer());
			runSafely(new JacksonInitializer());
			runSafely(new CharsetInitializer());
			preinitializationComplete.countDown();
		}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值