我是靠谱客的博主 淡淡煎蛋,最近开发中收集的这篇文章主要介绍spring boot 源码学习2 - SpringApplication#run,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

SpringApplication#run方法

      • 第一步:StopWatch
      • 第二步:configureHeadlessProperty
      • 第三步:SpringApplicationRunListeners
        • getRunListeners(args)方法:
        • listeners.starting()方法:

初始化SpringApplication之后,执行run方法,来创建和刷新一个ApplicationContext:

	public ConfigurableApplicationContext run(String... args) {
        //1、任务计时器,调用start开始计时
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		// 2、设置系统属性java.awt.headless,这里设置为true(Headless模式是在缺少显示屏、键盘或者鼠标时的系统配置)
		configureHeadlessProperty();
        // 3、使用SpringFactoriesLoader,获取资源文件中的SpringApplicationRunListener,此处是EventPublishingRunListener,并starting
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
            //4、创建一个DefaultApplicationArguments对象持有的是传进来的参数
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
            // 5、打印banner
			Banner printedBanner = printBanner(environment);
            // 6、创建context
			context = createApplicationContext();
            // 7、初始化FailureAnalyzers,借助SpringFactoriesLoader,创建Error Reporters
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			// 8、调用prepareContext,context相关的重要处理
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			// 9、用AbstractApplicationContext#refresh方法,并注册钩子
		    refreshContext(context);		
		    // 10、刷新的后置处理,未做操作
			afterRefresh(context, applicationArguments);
			// 11、停止计时
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			// 12、在容器完成刷新后,依次调用注册的Runners
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

主要的步骤标注在了代码里,以下做个简要的分析

第一步:StopWatch

		StopWatch stopWatch = new StopWatch();
		stopWatch.start();

start方法:

	public void start() throws IllegalStateException {
	    // 启动一个未命名的task
		start("");
	}
	
 	// start
 	public void start(String taskName) throws IllegalStateException {
 	    // 当前taskName不为null时,抛出异常
		if (this.currentTaskName != null) {
			throw new IllegalStateException("Can't start StopWatch: it's already running");
		}
		this.currentTaskName = taskName;
		this.startTimeNanos = System.nanoTime();
	}

在run方法11步中,结束计时。此方法比较简单。

	public void stop() throws IllegalStateException {
		if (this.currentTaskName == null) {
			throw new IllegalStateException("Can't stop StopWatch: it's not running");
		}
		long lastTime = System.nanoTime() - this.startTimeNanos;
		// task耗时
		this.totalTimeNanos += lastTime;
		// task基本信息(名称和结束时间)
		this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);
		if (this.keepTaskList) {
			this.taskList.add(this.lastTaskInfo);
		}
		// task数量
		++this.taskCount;
		this.currentTaskName = null;
	}

第二步:configureHeadlessProperty

Headless模式是系统的一种配置模式。在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式。

这段代码具体什么用,不清楚。

第三步:SpringApplicationRunListeners

getRunListeners(args)方法:

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

还是熟悉的配方,使用getSpringFactoriesInstances方法,返回EventPublishingRunListener实例。

注意:在使用createSpringFactoriesInstances方法,根据构造方法实例化EventPublishingRunListener对象时,将SpringApplication中的listener添加到了EventPublishingRunListener中的initialMulticaster中。

	public EventPublishingRunListener(SpringApplication application, String[] args) {
		this.application = application;
		this.args = args;
		this.initialMulticaster = new SimpleApplicationEventMulticaster();
		for (ApplicationListener<?> listener : application.getListeners()) {
			this.initialMulticaster.addApplicationListener(listener);
		}
	}

然后初始化SpringApplicationRunListeners对象:

	SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
		this.log = log;
		this.listeners = new ArrayList<>(listeners);
	}

listeners.starting()方法:

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

此处的listeners只有一个:

	public void starting() {
	    // 发送ApplicationStartingEvent
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}
	
	// SimpleApplicationEventMulticaster#multicastEvent
	public void multicastEvent(ApplicationEvent event) {
        this.multicastEvent(event, this.resolveDefaultEventType(event));
    }
    
	// multicastEvent
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		// 获取执行器,默认为null(这里可作为异步还是同步执行的扩展点)
		Executor executor = getTaskExecutor();
		// 遍历listener,进行回调
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}
    }

AbstractApplicationEventMulticaster#getApplicationListeners

	protected Collection<ApplicationListener<?>> getApplicationListeners(
			ApplicationEvent event, ResolvableType eventType) {
		// 此处source为:org.springframework.boot.context.event.ApplicationStartingEvent
		Object source = event.getSource();
		Class<?> sourceType = (source != null ? source.getClass() : null);
		// 构造cache
		ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

		// Quick check for existing entry on ConcurrentHashMap...
		// cache中有则直接返回
		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);
				// 检索application listeners,指定了event 和source type.
				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);
		}
	}
 	
 	// retrieveApplicationListeners,实际的检索方法
 	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为空
			listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
		}

		// Add programmatically registered listeners, including ones coming
		// from ApplicationListenerDetector (singleton beans and inner beans).
		for (ApplicationListener<?> listener : listeners) {
			//根据event和source type判断listener是否支持处理
			//使用GenericApplicationListener接口中的boolean supportsEventType(ResolvableType eventType)方法
			//和default boolean supportsSourceType(@Nullable Class<?> sourceType) 
			if (supportsEvent(listener, eventType, sourceType)) {
				if (retriever != null) {
					retriever.applicationListeners.add(listener);
				}
				allListeners.add(listener);
			}
		}

		// Add listeners by bean name, potentially overlapping with programmatically
		// registered listeners above - but here potentially with additional metadata.
		if (!listenerBeans.isEmpty()) {
			//省略掉此处代码...
		}

		AnnotationAwareOrderComparator.sort(allListeners);
		if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
			retriever.applicationListeners.clear();
			retriever.applicationListeners.addAll(allListeners);
		}
		return allListeners;
	}

此处的allListeners有:

org.springframework.boot.context.config.DelegatingApplicationListener
org.springframework.boot.context.logging.LoggingApplicationListener
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
BackgroundPreinitializer

如果想要知道它们做了什么操作,只需要查看对应的onApplicationEvent方法即可。

LoggingApplicationListener:

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

	//get()
	public static LoggingSystem get(ClassLoader classLoader) {
		String loggingSystem = System.getProperty(SYSTEM_PROPERTY);
		if (StringUtils.hasLength(loggingSystem)) {
			if (NONE.equals(loggingSystem)) {
				return new NoOpLoggingSystem();
			}
			return get(classLoader, loggingSystem);
		}
		//SYSTEMS变量在static块中初始化了
		//返回loggingSystem为:LogbackLoggingSystem
		return SYSTEMS.entrySet().stream().filter((entry) -> ClassUtils.isPresent(entry.getKey(), classLoader))
				.map((entry) -> get(classLoader, entry.getValue())).findFirst()
				.orElseThrow(() -> new IllegalStateException("No suitable logging system located"));
	}

BackgroundPreinitializer,DelegatingApplicationListener来说,没有做任何事。(此处的event为org.springframework.boot.context.event.ApplicationStartingEvent,如果方法中做了instanceof判断,则可能不会走逻辑)

LiquibaseServiceLocatorApplicationListener:

	public void onApplicationEvent(ApplicationStartingEvent event) {
	    // 当前场景不存在,liquibase.servicelocator.ServiceLocator,此方法也未执行
		if (ClassUtils.isPresent("liquibase.servicelocator.CustomResolverServiceLocator",
				event.getSpringApplication().getClassLoader())) {
			new LiquibasePresent().replaceServiceLocator();
		}
	}

SimpleApplicationEventMulticaster#invokeListener

	protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
		ErrorHandler errorHandler = getErrorHandler();
		// 如果有错误处理,则在catch中调用了handleError方法
		if (errorHandler != null) {
			try {
				doInvokeListener(listener, event);
			}
			catch (Throwable err) {
				errorHandler.handleError(err);
			}
		}
		else {
			doInvokeListener(listener, event);
		}
	}

	// doInvokeListener
	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
			// 回调
			listener.onApplicationEvent(event);
		}
		catch (ClassCastException ex) {
			String msg = ex.getMessage();
			if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception and just log a debug message.
				Log logger = LogFactory.getLog(getClass());
				if (logger.isTraceEnabled()) {
					logger.trace("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}

最后

以上就是淡淡煎蛋为你收集整理的spring boot 源码学习2 - SpringApplication#run的全部内容,希望文章能够帮你解决spring boot 源码学习2 - SpringApplication#run所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部