您的当前位置:首页正文

SpringBoot启动流程

来源:尚车旅游网
SpringBoot启动流程

SpringBoot启动流程

整个启动流程包含,推断 WEB 应⽤类型,设置初始化器,设置 ApplicationListener 监听器,获取并启动 SpringApplicationRunListener 类,准备 Spring 环境,创建并执⾏banner 打印类,创建应⽤上下⽂,准备应⽤上下⽂,刷新应⽤上下⽂,刷新应⽤上下⽂之后的调⽤,执⾏所有的 Runner 运⾏器。

@SpringBootApplicationpublic class MainApplication {

public static void main(String[] args) {

SpringApplication.run(MainApplication.class, args); }}

初始化主要加载资源类到集合中

推断当前 WEB 应⽤类型(NONE、SERVLET、REACTIVE)设置应⽤上下⽂初始化器设置 ApplicationListener 监听器推断主⼊⼝应⽤类

// 创建⼀个新的实例,这个应⽤上下⽂将从指定的来源加载 Bean

public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) { // 初始化资源加载器,默认 null

this.resourceLoader = resourceLoader; // 断⾔主资源不能为空

Assert.notNull(primarySources, \"PrimarySources must not be null\"); // 初始化主要加载资源类集合并去重

this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); // 推断当前 WEB 应⽤类型,NONE、SERVLET、REACTIVE

this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 加载引导程序(2.4.0增加的功能)

this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class)); // 设置初始化器

setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 设置监听器

setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); // 推断主⼊⼝应⽤类

this.mainApplicationClass = deduceMainApplicationClass();}

创建引导上下⽂

获取并启动所有 SpringApplicationRunListener 对象创建默认的应⽤参数类准备 Spring 应⽤环境创建并执⾏ banner 打印类创建应⽤上下⽂准备应⽤上下⽂刷新应⽤上下⽂

public ConfigurableApplicationContext run(String... args) { // 创建并启动计时监控类

StopWatch stopWatch = new StopWatch(); stopWatch.start(); // 创建引导上下⽂

DefaultBootstrapContext bootstrapContext = createBootstrapContext(); ConfigurableApplicationContext context = null; // 设置系统属性“java.awt.headless”的值,默认为 true configureHeadlessProperty();

// 创建所有 Spring 运⾏监听器并发布应⽤启动事件,

SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(bootstrapContext, this.mainApplicationClass); try {

// 初始化默认应⽤参数类

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 根据运⾏监听器、引导上下⽂、应⽤参数来准备 Spring 环境

ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); // 将要忽略的 bean 参数打开

configureIgnoreBeanInfo(environment); // 创建并执⾏ banner 打印类

Banner printedBanner = printBanner(environment); // 创建应⽤上下⽂

context = createApplicationContext(); // 设置应⽤程序启动 步骤

context.setApplicationStartup(this.applicationStartup); // 准备应⽤上下⽂

prepareContext(bootstrapContext, 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, listeners); throw new IllegalStateException(ex); } try {

// 发布应⽤上下⽂就绪事件 listeners.running(context); }

catch (Throwable ex) {

handleRunFailure(context, ex, null); throw new IllegalStateException(ex); }

return context;}

创建并启动引导上下⽂,2.4.0 之后的版本增加的新功能

private DefaultBootstrapContext createBootstrapContext() {

DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext(); this.bootstrappers.forEach((initializer) -> initializer.intitialize(bootstrapContext)); return bootstrapContext;}

// 从 META-INF/spring.factories 中获取所有的配置类,并将其封装到 SpringApplicationRunListeners 对象中去,主要创建的对象为 EventPublishingRunListenerprivate SpringApplicationRunListeners getRunListeners(String[] args) { Class[] types = new Class[] { SpringApplication.class, String[].class };

return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup);}

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

void starting(ConfigurableBootstrapContext bootstrapContext, Class mainApplicationClass) { doWithListeners(\"spring.boot.application.starting\ (step) -> {

if (mainApplicationClass != null) {

step.tag(\"mainApplicationClass\ } });}

// ⼴播事件

public void starting(ConfigurableBootstrapContext bootstrapContext) { this.initialMulticaster

.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));}

// applicationStartingEvent 是 SpringBoot 框架最早执⾏的监听器,在该监听器执⾏ started ⽅法时,会继续发布事件,主要是基于 Spring 的事件机制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); } }}

// 返回与给定事件匹配的监听器

protected Collection> getApplicationListeners( ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource();

Class sourceType = (source != null ? source.getClass() : null);

ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); // Potential new retriever to populate

CachedListenerRetriever newRetriever = null;

// Quick check for existing entry on ConcurrentHashMap

CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey); if (existingRetriever == null) {

// Caching a new ListenerRetriever if possible if (this.beanClassLoader == null ||

(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&

(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { newRetriever = new CachedListenerRetriever();

existingRetriever = this.retrieverCache.putIfAbsent(cacheKey, newRetriever); if (existingRetriever != null) {

newRetriever = null; // no need to populate it in retrieveApplicationListeners } } }

if (existingRetriever != null) {

Collection> result = existingRetriever.getApplicationListeners(); if (result != null) { return result; }

// If result is null, the existing retriever is not fully populated yet by another thread. // Proceed like caching wasn't possible for this current local attempt. }

return retrieveApplicationListeners(eventType, sourceType, newRetriever);}

Source 继承⾃ SimpleCommandLinePropertySource,⽤于解析简单的命令⾏参数

public DefaultApplicationArguments(String... args) { Assert.notNull(args, \"Args must not be null\"); this.source = new Source(args); this.args = args;}

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,

DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) { // Create and configure the environment // 创建或者获取应⽤环境

ConfigurableEnvironment environment = getOrCreateEnvironment(); // 配置应⽤环境

configureEnvironment(environment, applicationArguments.getSourceArgs()); ConfigurationPropertySources.attach(environment);

// listeners 环境准备,⼴播 ApplicationEnvironmentPreparedEvent listeners.environmentPrepared(bootstrapContext, environment); // 附加配置源

DefaultPropertiesPropertySource.moveToEnd(environment); // 配置其他激活⽂件

configureAdditionalProfiles(environment); // 将环境绑定给当前应⽤程序

bindToSpringApplication(environment); if (!this.isCustomEnvironment) {

environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); }

// 配置 propertySource 对它⾃⼰的递归依赖

ConfigurationPropertySources.attach(environment); return environment;}

打印 banner 的详细操作过程

private Banner printBanner(ConfigurableEnvironment environment) { if (this.bannerMode == Banner.Mode.OFF) { return null; }

ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader : new DefaultResourceLoader(null);

SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner); if (this.bannerMode == Mode.LOG) {

return bannerPrinter.print(environment, this.mainApplicationClass, logger); }

return bannerPrinter.print(environment, this.mainApplicationClass, System.out);}

根据不同的应⽤类型初始化不同的⼭下⽂应⽤类

protected ConfigurableApplicationContext createApplicationContext() { return this.applicationContextFactory.create(this.webApplicationType);}

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListener // 设置应⽤上下⽂的 environment context.setEnvironment(environment); // 应⽤⼭下⽂的后置处理 postProcessApplicationContext(context); // 为上下⽂应⽤所有初始化器,执⾏前⾯设置的 ApplicationContextInitializer 类 applyInitializers(context); // 触发所有 SpringApplicationRunListener 监听器的 contextPrepared 事件⽅法。添加所有的事件监听器 listeners.contextPrepared(context); bootstrapContext.close(context); // 记录启动⽇志 if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans // 注册启动参数bean,将容器指定的参数封装成bean,注⼊容器 ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton(\"springApplicationArguments\ if (printedBanner != null) { beanFactory.registerSingleton(\"springBootBanner\ } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } // Load the sources // 加载所有资源 Set sources = getAllSources(); Assert.notEmpty(sources, \"Sources must not be empty\"); // 将 bean 加载到上下⽂中 load(context, sources.toArray(new Object[0])); // 触发所有 SpringApplicationRunListener 监听器的 contextLoaded 事件⽅法 listeners.contextLoaded(context);}protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) {

logger.debug(\"Loading source \" + StringUtils.arrayToCommaDelimitedString(sources)); }

BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); if (this.beanNameGenerator != null) {

loader.setBeanNameGenerator(this.beanNameGenerator); }

if (this.resourceLoader != null) {

loader.setResourceLoader(this.resourceLoader); }

if (this.environment != null) {

loader.setEnvironment(this.environment); }

loader.load();}

// 后续会使⽤其将主资源加载到上下⽂中去,供后续解析使⽤

BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) { Assert.notNull(registry, \"Registry must not be null\"); Assert.notEmpty(sources, \"Sources must not be empty\"); this.sources = sources;

this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);

this.xmlReader = (XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null); this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null); this.scanner = new ClassPathBeanDefinitionScanner(registry); this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));}

void load() {

for (Object source : this.sources) { load(source); }}

private void load(Object source) {

Assert.notNull(source, \"Source must not be null\"); if (source instanceof Class) { // Class 的⽅式加载 load((Class) source); return; }

if (source instanceof Resource) { // Resource 资源的⽅式加载 load((Resource) source); return; }

if (source instanceof Package) { load((Package) source); return; }

if (source instanceof CharSequence) { load((CharSequence) source); return; }

throw new IllegalArgumentException(\"Invalid source type \" + source.getClass());}

private void load(Class source) {

if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) { // Any GroovyLoaders added in beans{} DSL can contribute beans here

GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class); ((GroovyBeanDefinitionReader) this.groovyReader).beans(loader.getBeans()); }

if (isEligible(source)) {

// 将符合条件的类注册到应⽤上下⽂ this.annotatedReader.register(source); }}

// 不是常规的闭包并且不是匿名类,即可private boolean isEligible(Class type) {

return !(type.isAnonymousClass() || isGroovyClosure(type) || hasNoConstructors(type));}

最终会调⽤到 AbstractApplicationContext 抽象类中的 refresh() ⽅法中去

refreshContext(context);

空⽅法,⽤于扩展

执⾏所有 Runner 执⾏器,执⾏所有 ApplicationRunner 和 CommandLineRunner 两种运⾏器。

private void callRunners(ApplicationContext context, ApplicationArguments args) { List runners = new ArrayList<>();

runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); AnnotationAwareOrderComparator.sort(runners); for (Object runner : new LinkedHashSet<>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); }

if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } }}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 版权所有