三、Springboot源码解析:SpringApplication#run(1)

创建完SpringApplication对象之后,接下来就是调用其run方法了,源码如下:

	public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		FailureAnalyzers analyzers = null;
		//即便没有显示器,也允许其启动
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			analyzers = new FailureAnalyzers(context);
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			listeners.finished(context, null);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			return context;
		}
		catch (Throwable ex) {
			handleRunFailure(context, listeners, analyzers, ex);
			throw new IllegalStateException(ex);
		}
	}

一步一步看吧。

一、StopWatch

这是一个秒表,用于记录程序的耗时时间,源码非常简单,一个StopWatch代表一组任务(taskList),其中有一个内部类TaskInfo代表一组任务中的某一个任务,内部类中记录了该任务的耗时时间和任务名称,用法如下:
在这里插入图片描述

二、获取SpringApplicationRunListeners

那么问题又来了,什么是SpringApplicationRunListeners?如何获取的?该类的注释写的非常好:Listener for the SpringApplication run method. SpringApplicationRunListeners are loaded via the SpringFactoriesLoader and should declare a public constructor that accepts a SpringApplication instance and a String[] of arguments. A new SpringApplicationRunListener instance will be created for each run.意思就是该类是SpringApplication类中run方法的监听器,SpringApplicationRunListeners和ApplicationContextInitializer、ApplicationListener一样是通过SpringFactoriesLoader在spring.factories中获取的。debug了一下源代码,发现只有spring-boot-1.5.8.RELEASE.jar的spring.factories有org.springframework.boot.SpringApplicationRunListener对应的值:org.springframework.boot.context.event.EventPublishingRunListener,而SpringApplicationRunListeners表示的是SpringApplicationRunListener的集合,该集合的长度为1。
接下来会执行listeners.starting()这段代码:

public void starting() {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.starting();
		}
	}

接着调用SpringApplicationRunListener的starting方法,按照上面我们说的,此处SpringApplicationRunListener对应的实现类为org.springframework.boot.context.event.EventPublishingRunListener,那就来看看它的starting方法是什么样的:

public void starting() {
	this.initialMulticaster
			.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
}

从代码的命名来看,像是一个组播器initialMulticaster发布了一个ApplicationStartedEvent事件,在真正发布事件之前,会先将事件解析为ResolvableType,流程图如下:在这里插入图片描述
从代码来看,就是根据ApplicationStartedEvent构造出来一个ResolvableType,什么是ResolvableType呢:在这里插入图片描述
其实对于它的定位就是一个反射的工具类,可以让我们更方便地获取类的信息,解析完这个事件之后,就要真正发布事件了:在这里插入图片描述
我们看到,在真正发布事件之前,会先调用图5中的方法,获取与该事件匹配的监听器,代码如下:

final Map<ListenerCacheKey, ListenerRetriever> retrieverCache =
			new ConcurrentHashMap<ListenerCacheKey, ListenerRetriever>(64);
private Object retrievalMutex = this.defaultRetriever;
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
private Object retrievalMutex = this.defaultRetriever;
			
protected Collection<ApplicationListener<?>> getApplicationListeners(
			ApplicationEvent event, ResolvableType eventType) {
	//获取事件源
	Object source = event.getSource();
	Class<?> sourceType = (source != null ? source.getClass() : null);
	//由下面代码的命名可以大致猜测出,这一部分的代码想使用缓存,而下面的一行代码就是创建一个缓存键,ListenerCacheKey类是本类的一个内部类
	ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

	// Quick check for existing entry on ConcurrentHashMap...
	//ListenerRetriever是该类中的一个变量,数据结构为ConcurrentHashMap
	//获取上一个cacheKey对应的ListenerRetriever,ListenerRetriever是该类的一个内部类,retrieve的意思是检索,
	ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
	//此处retriever的值为null,所以if方法体的代码不会被执行
	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
		//retrievalMutex是该类的一个变量,它的值为ListenerRetriever的一个实例对象,它有一个属性Set<ApplicationListener<?>> applicationListeners的值为SpringApplication对象中存储的所有ApplicationListener,一共10个,该ListenerRetriever对象该属性的初始化是发生在实例化EventPublishingRunListener对象是赋值的。
		synchronized (this.retrievalMutex) {
			//retriever是该类的一个变量,值为一个空的ConcurrentHashMap,此处get的结果为null
			retriever = this.retrieverCache.get(cacheKey);
			if (retriever != null) {
				return retriever.getApplicationListeners();
			}
			//新建一个ListenerRetriever
			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, Class<?> sourceType, ListenerRetriever retriever) {
	//存放所有的监听器
	LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
	Set<ApplicationListener<?>> listeners;
	Set<String> listenerBeans;
	synchronized (this.retrievalMutex) {
		//把上面我们提到的10个监听器赋值给listeners
		listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
		//listenerBeans初始化,集合内没有元素,因为applicationListenerBeans的长度为0
		listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
	}
	for (ApplicationListener<?> listener : listeners) {
		//判断是否是符合该listener的时间
		if (supportsEvent(listener, eventType, sourceType)) {
			if (retriever != null) {
				//添加符合条件的listener
				retriever.applicationListeners.add(listener);
			}
			allListeners.add(listener);
		}
	}
	if (!listenerBeans.isEmpty()) {
		//获取BeanFactory
		BeanFactory beanFactory = getBeanFactory();
		for (String listenerBeanName : listenerBeans) {
			try {
				Class<?> listenerType = beanFactory.getType(listenerBeanName);
				if (listenerType == null || supportsEvent(listenerType, eventType)) {
					ApplicationListener<?> listener =
							beanFactory.getBean(listenerBeanName, ApplicationListener.class);
					if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
						if (retriever != null) {
							retriever.applicationListenerBeans.add(listenerBeanName);
						}
						allListeners.add(listener);
					}
				}
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Singleton listener instance (without backing bean definition) disappeared -
				// probably in the middle of the destruction phase
			}
		}
	}
	AnnotationAwareOrderComparator.sort(allListeners);
	return allListeners;
}

protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) {
	GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
			(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
	return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}

对于上面代码,这里做一个简单总结,在初始化SpringApplication对象的时候,我们初始化了一个监听器对象列表,这里通过getApplicationListeners(event, type)筛选出监听应用启动事件的监听器,一共有四个:在这里插入图片描述
然后就是发布事件了:

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);
		}
	}
}

接下来分别执行这四个监听器的onApplicationEvent方法,它们分别做了什么事呢?
1、LoggingApplicationListener

private LoggingSystem loggingSystem;
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
	this.loggingSystem = LoggingSystem
			.get(event.getSpringApplication().getClassLoader());
	this.loggingSystem.beforeInitialize();
}

从代码来看,应该是初始化日志系统,因为这里不涉及比较核心的东西,就一笔带过。
2、BackgroundPreinitializer

	@Override
	public void onApplicationEvent(SpringApplicationEvent event) {
		if (event instanceof ApplicationEnvironmentPreparedEvent) {
			if (preinitializationStarted.compareAndSet(false, true)) {
				performPreinitialization();
			}
		}
		if ((event instanceof ApplicationReadyEvent
				|| event instanceof ApplicationFailedEvent)
				&& preinitializationStarted.get()) {
			try {
				preinitializationComplete.await();
			}
			catch (InterruptedException ex) {
				Thread.currentThread().interrupt();
			}
		}
	}

debug了一下发现,上面的方法体中if的条件均不满足,没有执行任何实质性的代码。
3、DelegatingApplicationListener

	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationEnvironmentPreparedEvent) {
			List<ApplicationListener<ApplicationEvent>> delegates = getListeners(
					((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
			if (delegates.isEmpty()) {
				return;
			}
			this.multicaster = new SimpleApplicationEventMulticaster();
			for (ApplicationListener<ApplicationEvent> listener : delegates) {
				this.multicaster.addApplicationListener(listener);
			}
		}
		if (this.multicaster != null) {
			this.multicaster.multicastEvent(event);
		}
	}

和上一步一样,什么都没执行。
4、LiquibaseServiceLocatorApplicationListener

	public void onApplicationEvent(ApplicationStartingEvent event) {
		if (ClassUtils.isPresent("liquibase.servicelocator.ServiceLocator", null)) {
			new LiquibasePresent().replaceServiceLocator();
		}
	}

也没做什么实质的东西,这里主要就是看下类路径有没有liquibase.servicelocator.ServiceLocator这个类,如果有就替换一下,猜想可能是为了修复什么漏洞而添加的一个监听器。

三、总结

本篇主要介绍了如下几个要点:

  • 启动StopWatch
  • 从spring.factories中获取SpringApplicationRunListeners的实例,该监听器可以理解为整个run方法的监听器,调用它的starting方法,发布一个ApplicationStartedEvent事件
  • 从SpringApplication中所有的监听器中筛选出监听改事件的监听器,一共筛选出了四个
  • 筛选出的四个监听器分别响应该事件,只有LoggingApplicationListener做了一些实质性的工作,那就是日志系统的初始化。

四、the next…

解析以下三行代码:

  • ApplicationArguments applicationArguments = new DefaultApplicationArguments(
    args);
  • ConfigurableEnvironment environment = prepareEnvironment(listeners,
    applicationArguments);
  • Banner printedBanner = printBanner(environment);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值