Spring Boot 启动流程 Spring Boot 入口 一般会使用静态方法,也可以自己 new 一个 SpringApplication
,或者使用 Buidler 定制化。
1 2 3 4 5 6 7 @SpringBootApplication public class StartupApplication { public static void main (String[] args) { SpringApplication.run(StartupApplication.class, args); } }
SpringApplication 构造器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public SpringApplication (ResourceLoader resourceLoader, Class<?>... primarySources) { this .resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null" ); this .primarySources = new LinkedHashSet <>(Arrays.asList(primarySources)); this .webApplicationType = WebApplicationType.deduceFromClasspath(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this .mainApplicationClass = deduceMainApplicationClass(); }
上面之所以要加载 ApplicationListener
保存到 SpringApplication
,是因为下面要传递给 ApplicationEventMulticaster
。SpringApplication
作为 EventPublishingRunListener
参数传入。
SpringApplication
运行方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 public ConfigurableApplicationContext run (String... args) { StopWatch stopWatch = new StopWatch (); stopWatch.start(); ConfigurableApplicationContext context = null ; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments (args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); context = createApplicationContext(); 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); 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; }
StopWatch 计时器/秒表
1 2 StopWatch stopWatch = new StopWatch ();stopWatch.start();
设置属性 java.awt.headless
,如果不存在默认值设置为 true
1 2 3 4 private void configureHeadlessProperty () { System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this .headless))); }
getRunListeners 该方法返回一个 SpringApplicationRunListeners
实例,注意末尾有一个 “s”。
1 2 3 4 5 6 7 private SpringApplicationRunListeners getRunListeners (String[] args) { Class<?>[] types = new Class <?>[] { SpringApplication.class, String[].class }; return new SpringApplicationRunListeners (logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this , args)); }
照应前面所说,之所以将 SpringApplication
传入,作为后续的构造器参数,是因为后面需要往 ApplicationEventMulticaster
加入 ApplicationListener
,而 ApplicationListener
已经在 SpringApplication
的构造器加载完毕
1 2 3 4 5 6 7 8 private <T> Collection<T> getSpringFactoriesInstances (Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); Set<String> names = new LinkedHashSet <>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
一般情况下,只有 spring-boot 下面的 spring.factories 配置了一个 EventPublishingRunListener
,其构造器如下:
1 2 3 4 5 6 7 8 9 10 11 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); } }
listeners.starting() 在获得了 SpringApplicationRunListeners
之后立即发布一个事件,告诉所有 ApplicationListener
容器正在启动。
通常这里只有 1 个 listeners,即 EventPublishingRunListener
。
1 2 3 4 5 void starting () { for (SpringApplicationRunListener listener : this .listeners) { listener.starting(); } }
EventPublishingRunListener
底层调用内部的 Multicaster
进行广播。
1 2 3 4 public void starting () { this .initialMulticaster.multicastEvent(new ApplicationStartingEvent (this .application, this .args)); }
1 2 3 4 public void multicastEvent (ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); }
1 2 3 4 5 6 7 8 9 10 11 12 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); } } }
获得关心该事件的 ApplicationListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource(); Class<?> sourceType = (source != null ? source.getClass() : null ); ListenerCacheKey cacheKey = new ListenerCacheKey (eventType, sourceType); CachedListenerRetriever newRetriever = null ; CachedListenerRetriever existingRetriever = this .retrieverCache.get(cacheKey); if (existingRetriever == null ) { 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 ; } } } if (existingRetriever != null ) { Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners(); if (result != null ) { return result; } } return retrieveApplicationListeners(eventType, sourceType, newRetriever); }
默认情况下,这里会根据 Starting 事件匹配到 4 个:
LoggingApplicationListener
BackgroundPreinitializer
DelegatingApplicationListener
LiquibaseServiceLocatorApplicationListener
prepareEnvironment 准备环境。也会发布事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private ConfigurableEnvironment prepareEnvironment ( SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { 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; }
补充一下 StandardServletEnvironment
构造器做了什么:
1 2 3 4 5 6 public AbstractEnvironment () { customizePropertySources(this .propertySources); }
以下是 StandardServletEnvironment
对于 customizePropertySources
的覆盖(定制化):
1 2 3 4 5 6 7 8 9 10 11 12 protected void customizePropertySources (MutablePropertySources propertySources) { propertySources.addLast(new StubPropertySource (SERVLET_CONFIG_PROPERTY_SOURCE_NAME)); propertySources.addLast(new StubPropertySource (SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)); if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) { propertySources.addLast(new JndiPropertySource (JNDI_PROPERTY_SOURCE_NAME)); } super .customizePropertySources(propertySources); }
以下是 StandardEnvironement
关于 customizePropertySources
方法的覆盖(定制化):
1 2 3 4 5 6 7 8 9 protected void customizePropertySources (MutablePropertySources propertySources) { propertySources.addLast( new PropertiesPropertySource (SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties())); propertySources.addLast( new SystemEnvironmentPropertySource (SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment())); }
prepareContext 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private void prepareContext (ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { context.setEnvironment(environment); postProcessApplicationContext(context); applyInitializers(context); listeners.contextPrepared(context); if (this .logStartupInfo) { logStartupInfo(context.getParent() == null ); logStartupProfileInfo(context); } ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments" , applicationArguments); if (printedBanner != null ) { beanFactory.registerSingleton("springBootBanner" , printedBanner); } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this .allowBeanDefinitionOverriding); } if (this .lazyInitialization) { context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor ()); } Set<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty" ); load(context, sources.toArray(new Object [0 ])); listeners.contextLoaded(context); }