Want to know how your SpringBoot is to start it? Look!

SpringBoot start process analysis

SpringBoot start the process mainly of two parts, one part is creating SpringApplicationthe time, in part, in the Runmethod in

Here Insert Picture Description

1. First look SpringApplication constructor
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 资源加载器
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        
 // 1. 可能的web应用程序类型的类型。
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
        
// 2. 设置初始化应用context
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        
// 3.设置初始化监听
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
      
// 4. 推演主程序类
		this.mainApplicationClass = deduceMainApplicationClass();
	}

Here Insert Picture Description

1. Possible types of web application type.

This code is to infer what our application is a web application
Here Insert Picture Description

2. Set the application context initialization

Set in the context of the application initialization time, is the first implementation of the `getSpringFactoriesInstances (ApplicationContextInitializer.class) method, the argument is ApplicationContextInitializer.class bytecode object
Here Insert Picture Description
Let's look at how he loaded those classes
start to get the cache, if there is no taken from a resource file
Here Insert Picture Description
Here Insert Picture Description
, double-click Shift search spring.factories can see that it exists in the project

Here Insert Picture Description

We needed to get from the Map class initialization org.springframework.context.ApplicationContextInitializer class according to the type of breakpoint enters getOrDefault (factoryClassName, Collections.emptyList ()); methods, is then loaded into the set of classes into standby

3. Initialize the listener class

And initializes the application context is no different,
the only difference is getSpringFactoriesInstances (ApplicationListener.class)) · ApplicationListener.class pass in is so not repeat them here.

4. The deduction of the main program

Here Insert Picture Description

Here to complete the process SpringBoot start the process of initializing SpringApplication.

Summary
SpringApplication process, can be divided into four steps:
derivation type web application (if not dependent on the type of web plus NONE)
Initialization ApplicationContextInitializer
initialization ApplicationListener
deduce main categories
By four step completes the first step of the initialization SpringApplication process.

2. In the Run method to see what all the
public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
        //计时器开始
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		// 配置Headless模式,是在缺少显示屏、键盘或者鼠标时的系统配置 
		// 默认为true
		configureHeadlessProperty();
        //获取所有的监听器
		SpringApplicationRunListeners listeners = getRunListeners(args);
        //启动监听器
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //准备环境
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
            //配置忽略的bean
			configureIgnoreBeanInfo(environment);
            //打印banner
			Banner printedBanner = printBanner(environment);
            //创建容器
			context = createApplicationContext();
            //异常相关处理
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
            //准本应用上下文
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            //刷新容器
			refreshContext(context);
            //刷新容器后的扩展接口
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
            //发布监听应用上下文启动完成
			listeners.started(context);
            //执行runner
			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;
	}

Here to explain the key steps

1. Get all the Monitor

Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
This is very familiar with the code, its main role is to META-INFO / spring.properties loaded configuration SpringApplicationRunListener listener as follows:


# Run Listeners 
org.springframework.boot.SpringApplicationRunListener=\norg.springframework.boot.context.event.EventPublishingRunListener

Apparently only one event publishing listener class, got EventPublishingRunListener start publishing event listener, the next step is started up listeners.starting (); we look down with source code
Here Insert Picture Description

Start when they are actually created a ApplicationStartingEvent object is actually listening application launch event.
Which is a SimpleApplicationEventMulticaster initialMulticaster

@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        //获取线程池
		Executor executor = getTaskExecutor();
        //为每一个监听器创建一个线程
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}
2. Prepare the environment
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
        //配置环境
		configureEnvironment(environment, applicationArguments.getSourceArgs());
        
		ConfigurationPropertySources.attach(environment);
        //环境准备完成
		listeners.environmentPrepared(environment);
        
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
					deduceEnvironmentClass());
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}
3. Configure ignored Bean
4. Print Banner

Here Insert Picture Description
Here Insert Picture Description

This is customizable, it can also be a drawing or text file articles of graphics.

5. Create a container

Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Our environment is a servlet, DEFAULT_SERVLET_WEB_CONTEXT_CLASS servlet actually create objects by way of reflection

6. exception error handling

Here Insert Picture Description

But it is still to load SpringBootExceptionReporter class / spring.factories configuration file META-INFO

7. Prepare Application Context

Before you create here it will be based on the context of the preparation for the environment, as well as monitoring and other preparation application context

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
			SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
         //设置环境参数
		context.setEnvironment(environment);
        //设置后处理应用上下文
		postProcessApplicationContext(context);
        //把从spring.properties中加载的org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,进行初始化操作
		applyInitializers(context);
        //发布应用上下文事件
		listeners.contextPrepared(context);
        //打印启动日志
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}
		// Add boot specific singleton beans
        //注册一个名字是springApplicationArguments单例的bane
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
		if (printedBanner != null) {
        //注册一个名字是springBootBanner单例的bean
			beanFactory.registerSingleton("springBootBanner", printedBanner);
		}
        //是否允许类重名
		if (beanFactory instanceof DefaultListableBeanFactory) {
			((DefaultListableBeanFactory) beanFactory)
					.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
        //是否可以懒加载
		if (this.lazyInitialization) {
			context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
		}
		// Load the sources
        //获取所有的资源
		Set<Object> sources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");
        //创建BeanDefinitionLoader加载器加载所有的资源
		load(context, sources.toArray(new Object[0]));
        //发布上下文事件
		listeners.contextLoaded(context);
	}
8. refresh application context
public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
            //准备刷新上下文
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
            //通知子类刷新内部工厂
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
            //准备Bean工厂
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
             // 允许在上下文子类中对bean工厂进行后处理。
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
                //调用上下文中注册为bean的工厂处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
                //注册后置处理器
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
                //初始化信息源
				initMessageSource();

				// Initialize event multicaster for this context.
                //初始化上下文事件发布器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
                //初始化其他自定义bean
				onRefresh();

				// Check for listener beans and register them.
                //注册监听器
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
                //完成bean工厂初始化
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
                //完成刷新,清缓存,初始化生命周期,事件发布等
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
                //销毁Bean
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

In onRefresh () this method to create the Tomcat service
Here Insert Picture Description
Here Insert Picture Description

Creating a Tomcat object and set the parameters
Here Insert Picture Description
Here Insert Picture Description

Start tomcat service finishRefresh method
Here Insert Picture Description
Here Insert Picture Description

9. After the refresh process

afterRefresh () is a empty implementation, keep post-expansion

10. publish listens application launch event

Call context.publishEvent method, published application launch event ApplicationStartedEvent
Here Insert Picture Description

11. The Executive Runner

Get all ApplicationRunner and CommandLineRunner to initialize some parameters callRunner () is a callback function
Here Insert Picture Description

12. Publish the event context is ready

This code looks similar to the acquaintance, in front of a lot of similar code, the difference is released after a ApplicationReadyEvent event context here ready, ready to declare what application context
Here Insert Picture Description

Published 27 original articles · won praise 5 · Views 503

Guess you like

Origin blog.csdn.net/qq_38446413/article/details/105015378