Skip to content

Latest commit

 

History

History
665 lines (533 loc) · 20.7 KB

Spring-Boot-Run.md

File metadata and controls

665 lines (533 loc) · 20.7 KB

SpringBoot 启动方法

入口

  • 通常一个简单的 SpringBoot 基础项目我们会有如下代码
@SpringBootApplication@RestController@RequestMapping("/") publicclassApplication { publicstaticvoidmain(String[] args) { SpringApplication.run(Application.class, args); } }
  • 值得关注的有SpringApplication.run以及注解@SpringBootApplication

run 方法

publicConfigurableApplicationContextrun(String... args) { // 秒表StopWatchstopWatch = newStopWatch(); stopWatch.start(); ConfigurableApplicationContextcontext = null; Collection<SpringBootExceptionReporter> exceptionReporters = newArrayList<>(); configureHeadlessProperty(); // 获取监听器SpringApplicationRunListenerslisteners = getRunListeners(args); // 监听器启动listeners.starting(); try { // application 启动参数列表ApplicationArgumentsapplicationArguments = newDefaultApplicationArguments(args); ConfigurableEnvironmentenvironment = prepareEnvironment(listeners, applicationArguments); // 配置忽略的bean信息configureIgnoreBeanInfo(environment); BannerprintedBanner = printBanner(environment); // 创建应用上下文context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, newClass[] { ConfigurableApplicationContext.class }, context); // 准备上下文,装配beanprepareContext(context, environment, listeners, applicationArguments, printedBanner); // 上下文刷新refreshContext(context); // 刷新后做什么afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { newStartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); } // 监听器开始了listeners.started(context); // 唤醒callRunners(context, applicationArguments); } catch (Throwableex) { handleRunFailure(context, ex, exceptionReporters, listeners); thrownewIllegalStateException(ex); } try { // 监听器正式运行listeners.running(context); } catch (Throwableex) { handleRunFailure(context, ex, exceptionReporters, null); thrownewIllegalStateException(ex); } returncontext; }

getRunListeners

  • 获取监听器
privateSpringApplicationRunListenersgetRunListeners(String[] args) { Class<?>[] types = newClass<?>[] { SpringApplication.class, String[].class }; // 获取 Spring Factory 实例对象returnnewSpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)); } private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoaderclassLoader = getClassLoader(); // Use names and ensure unique to protect against duplicates// 读取 spring.factoriesSet<String> names = newLinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); // 创建SpringFactory实例List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); /** * 排序 {@link Ordered} */AnnotationAwareOrderComparator.sort(instances); returninstances; }

createSpringFactoriesInstances

@SuppressWarnings("unchecked") private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoaderclassLoader, Object[] args, Set<String> names) { // 初始化List<T> instances = newArrayList<>(names.size()); for (Stringname : names) { try { // 通过名字创建类的class对象Class<?> instanceClass = ClassUtils.forName(name, classLoader); Assert.isAssignable(type, instanceClass); // 构造器获取Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes); // 创建具体实例Tinstance = (T) BeanUtils.instantiateClass(constructor, args); // 加入实例表中instances.add(instance); } catch (Throwableex) { thrownewIllegalArgumentException("Cannot instantiate " + type + " : " + name, ex); } } returninstances; }
  • SpringFactoriesLoader.loadFactoryNames(type, classLoader) 是 spring 提供的方法,主要目的是读取spring.factories文件
    • 读取需要创建的内容

image-20200318080601725

  • 创建完成

    image-20200318080901881

  • AnnotationAwareOrderComparator.sort(instances)排序

    • 通过 spring 的源码我们知道这个方法是根据order的数字大小进行排序,观察

      SharedMetadataReaderFactoryContextInitializer

      image-20200318081112670

    • 同样的再找一个DelegatingApplicationContextInitializer

      image-20200318081322781

  • 下图中的所有类都有 Order 数值返回

    排序前:

image-20200318081352639

排序后:

image-20200318081458019

listeners.starting()

  • SpringApplicationRunListeners : org.springframework.boot.SpringApplicationRunListeners 这个类是org.springframework.boot.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(); } } } 
    • 这里主要是启动org.springframework.boot.SpringApplicationRunListener#starting方法,只有一个实现org.springframework.boot.context.event.EventPublishingRunListener#starting

prepareEnvironment

privateConfigurableEnvironmentprepareEnvironment(SpringApplicationRunListenerslisteners, ApplicationArgumentsapplicationArguments) { // Create and configure the environment// 得到一个环境ConfigurableEnvironmentenvironment = getOrCreateEnvironment(); // 配置环境configureEnvironment(environment, applicationArguments.getSourceArgs()); ConfigurationPropertySources.attach(environment); listeners.environmentPrepared(environment); // 绑定springBoot应用bindToSpringApplication(environment); // 是否创建自定义环境if (!this.isCustomEnvironment) { environment = newEnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); } ConfigurationPropertySources.attach(environment); returnenvironment; }

configureIgnoreBeanInfo

  • 获取spring.beaninfo.ignore并且设置到环境信息中
privatevoidconfigureIgnoreBeanInfo(ConfigurableEnvironmentenvironment) { if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) { Booleanignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE); System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString()); } }

printBanner

privateBannerprintBanner(ConfigurableEnvironmentenvironment) { if (this.bannerMode == Banner.Mode.OFF) { returnnull; } ResourceLoaderresourceLoader = (this.resourceLoader != null) ? this.resourceLoader : newDefaultResourceLoader(getClassLoader()); // 创建打印器SpringApplicationBannerPrinterbannerPrinter = newSpringApplicationBannerPrinter(resourceLoader, this.banner); if (this.bannerMode == Mode.LOG) { // 输出returnbannerPrinter.print(environment, this.mainApplicationClass, logger); } // 输出returnbannerPrinter.print(environment, this.mainApplicationClass, System.out); }
 Banner print(Environment environment, Class<?> sourceClass, PrintStream out) { Banner banner = getBanner(environment); banner.printBanner(environment, sourceClass, out); return new PrintedBanner(banner, sourceClass); } 
  • 最终输出内容类:org.springframework.boot.SpringBootBanner

    classSpringBootBannerimplementsBanner { privatestaticfinalString[] BANNER = { "", " . ____ _ __ _ _", " /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\\\\\\\", "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\\\\\\\", " \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )", " ' |____| .__|_| |_|_| |_\\__, | / / / /", " =========|_|==============|___/=/_/_/_/" }; privatestaticfinalStringSPRING_BOOT = " :: Spring Boot :: "; privatestaticfinalintSTRAP_LINE_SIZE = 42; @OverridepublicvoidprintBanner(Environmentenvironment, Class<?> sourceClass, PrintStreamprintStream) { for (Stringline : BANNER) { printStream.println(line); } Stringversion = SpringBootVersion.getVersion(); version = (version != null) ? " (v" + version + ")" : ""; StringBuilderpadding = newStringBuilder(); while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) { padding.append(" "); } printStream.println(AnsiOutput.toString(AnsiColor.GREEN, SPRING_BOOT, AnsiColor.DEFAULT, padding.toString(), AnsiStyle.FAINT, version)); printStream.println(); } }

createApplicationContext

protectedConfigurableApplicationContextcreateApplicationContext() { // 获取上下文类Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { // 根据不同类型选择创建的实例switch (this.webApplicationType) { caseSERVLET: contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); break; caseREACTIVE: contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); break; default: contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); } } catch (ClassNotFoundExceptionex) { thrownewIllegalStateException( "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex); } } return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); }
  • this.applicationContextClass 初始化方法
publicSpringApplication(ResourceLoaderresourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = newLinkedHashSet<>(Arrays.asList(primarySources)); // 设置 web应用类型this.webApplicationType = WebApplicationType.deduceFromClasspath(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }
  • org.springframework.boot.WebApplicationType#deduceFromClasspath
staticWebApplicationTypededuceFromClasspath() { if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null) && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) { returnWebApplicationType.REACTIVE; } for (StringclassName : SERVLET_INDICATOR_CLASSES) { if (!ClassUtils.isPresent(className, null)) { returnWebApplicationType.NONE; } } returnWebApplicationType.SERVLET; }

exceptionReporters

image-20200318085243888

prepareContext

privatevoidprepareContext(ConfigurableApplicationContextcontext, ConfigurableEnvironmentenvironment, SpringApplicationRunListenerslisteners, ApplicationArgumentsapplicationArguments, BannerprintedBanner) { // 上下文中设置环境context.setEnvironment(environment); // 上下文处理postProcessApplicationContext(context); // 初始化applyInitializers(context); // 监听器中放入上下文listeners.contextPrepared(context); if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beansConfigurableListableBeanFactorybeanFactory = context.getBeanFactory(); // 单例对象注册beanFactory.registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); } if (beanFactoryinstanceofDefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(newLazyInitializationBeanFactoryPostProcessor()); } // Load the sourcesSet<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); // 加载上下文load(context, sources.toArray(newObject[0])); // 监听器做加载上下文操作listeners.contextLoaded(context); }
  • set方法就不说了

postProcessApplicationContext

protectedvoidpostProcessApplicationContext(ConfigurableApplicationContextcontext) { if (this.beanNameGenerator != null) { // 注册 beanName 的生成器context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, this.beanNameGenerator); } if (this.resourceLoader != null) { if (contextinstanceofGenericApplicationContext) { // 设置资源加载器 ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader); } if (contextinstanceofDefaultResourceLoader) { // 设置类加载器 ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader()); } } if (this.addConversionService) { // 转换服务context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance()); } }
  • 看一下最终设置完成后的 context

    context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());

image-20200318090128983

image-20200318090312626

applyInitializers

  • 初始化应用上下文
@SuppressWarnings({ "rawtypes", "unchecked" }) protectedvoidapplyInitializers(ConfigurableApplicationContextcontext) { for (ApplicationContextInitializerinitializer : getInitializers()) { Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class); Assert.isInstanceOf(requiredType, context, "Unable to call initializer."); initializer.initialize(context); } }
  • 初始化 List<ApplicationListener<?>> listeners: setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));

  • 获取 List<ApplicationListener<?>> listeners: public Set<ApplicationListener<?>> getListeners() { return asUnmodifiableOrderedSet(this.listeners);}

  • 数据结果

image-20200318090935285

  • 子类的具体实现不展开了

getAllSources

publicSet<Object> getAllSources() { Set<Object> allSources = newLinkedHashSet<>(); if (!CollectionUtils.isEmpty(this.primarySources)) { allSources.addAll(this.primarySources); } if (!CollectionUtils.isEmpty(this.sources)) { allSources.addAll(this.sources); } returnCollections.unmodifiableSet(allSources); }
  • primarySources 就是我们的项目启动类,在SpringApplication的构造器中有this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources))

image-20200318091558233

load

  • 加载 bean 到应用上下文
protectedvoidload(ApplicationContextcontext, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources)); } // bean定义加载器BeanDefinitionLoaderloader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); if (this.beanNameGenerator != null) { // 设置 beanName生成器loader.setBeanNameGenerator(this.beanNameGenerator); } if (this.resourceLoader != null) { // 设置 资源加载器loader.setResourceLoader(this.resourceLoader); } if (this.environment != null) { // 设置环境loader.setEnvironment(this.environment); } // 加载loader.load(); }
intload() { intcount = 0; for (Objectsource : this.sources) { count += load(source); } returncount; }
privateintload(Objectsource) { Assert.notNull(source, "Source must not be null"); if (sourceinstanceofClass<?>) { returnload((Class<?>) source); } if (sourceinstanceofResource) { returnload((Resource) source); } if (sourceinstanceofPackage) { returnload((Package) source); } if (sourceinstanceofCharSequence) { returnload((CharSequence) source); } thrownewIllegalArgumentException("Invalid source type " + source.getClass()); }
  • 通过前文我们已经知道 source就是一个 class

    image-20200318092027020

privateintload(Class<?> source) { if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) { // Any GroovyLoaders added in beans{} DSL can contribute beans hereGroovyBeanDefinitionSourceloader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class); load(loader); } // 是否为组件if (isComponent(source)) { this.annotatedReader.register(source); return1; } return0; }
  • 我们的启动类是一个组件,直接注册完成返回 1

listeners.contextLoaded(context)

  • 监听器行为: 在上下文资源加载后做一些事情

refreshContext

  • 上下文刷新
privatevoidrefreshContext(ConfigurableApplicationContextcontext) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlExceptionex) { // Not allowed in some environments. } } }
/** * Refresh the underlying {@link ApplicationContext}. * @param applicationContext the application context to refresh */protectedvoidrefresh(ApplicationContextapplicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh(); }
  • 最终来到了org.springframework.context.support.AbstractApplicationContext#refresh方法,此方法是 spring 的一个方法,此处不在阐述

afterRefresh

  • 刷新上下文之后做的事情,空的没有实现

     protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) { } 

stopWatch.stop()

  • 秒表结束

listeners.started(context)

  • 各类监听器启动

callRunners

  • 两种 runner 启动ApplicationRunnerCommandLineRunner
privatevoidcallRunners(ApplicationContextcontext, ApplicationArgumentsargs) { List<Object> runners = newArrayList<>(); runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); AnnotationAwareOrderComparator.sort(runners); for (Objectrunner : newLinkedHashSet<>(runners)) { if (runnerinstanceofApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runnerinstanceofCommandLineRunner) { callRunner((CommandLineRunner) runner, args); } } }
privatevoidcallRunner(ApplicationRunnerrunner, ApplicationArgumentsargs) { try { (runner).run(args); } catch (Exceptionex) { thrownewIllegalStateException("Failed to execute ApplicationRunner", ex); } }

listeners.running(context)

  • 监听器正式开始工作
close