源碼分析:SpringBoot項目啓動過程

文章目錄

前置準備

SpringBoot源碼技術棧太過龐大,這裏只是簡版解讀,後續會細化部分源碼細節.

SpringApplication.run(…)

@SpringBootApplication
public class FactoryDemoApplication {

	public static void main(String[] args) {
        // 從Run開始Debug
		 SpringApplication.run(FactoryDemoApplication.class, args);
	}

}

創建SpringApplication

	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}
	
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		// 即傳入的pringApplication.run傳入的FactoryDemoApplication.class這個參數
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

推斷上下文類型

通過WebApplicationType.deduceFromClasspath()實現的,其實就是判斷指定類是不是存在。

 
 private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
			"org.springframework.web.context.ConfigurableWebApplicationContext" };

	private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";

	private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";

	private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

	private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";

	private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";

	static WebApplicationType deduceFromClasspath() {
		if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
				&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
			return WebApplicationType.REACTIVE;
		}
		for (String className : SERVLET_INDICATOR_CLASSES) {
			if (!ClassUtils.isPresent(className, null)) {
				return WebApplicationType.NONE;
			}
		}
		return WebApplicationType.SERVLET;
	}

設置初始化參數

setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));

通過SpringFactoriesLoader.loadFactoryNames(加載工廠類

SpringFactoriesLoader.loadFactoryNames(type, classLoader)會加載全部並放入緩存中,方便後續使用。

"com.example.factory.project.ChildGenerationConfiguration" -> {LinkedList@1984}  size = 2
"org.springframework.boot.autoconfigure.EnableAutoConfiguration" -> {LinkedList@1985}  size = 128
"org.springframework.beans.BeanInfoFactory" -> {LinkedList@1986}  size = 1
"org.springframework.boot.env.EnvironmentPostProcessor" -> {LinkedList@2022}  size = 6
"org.springframework.context.ApplicationContextInitializer" -> {LinkedList@2024}  size = 8
"org.springframework.context.ApplicationListener" -> {LinkedList@2026}  size = 13
"org.springframework.boot.diagnostics.FailureAnalyzer" -> {LinkedList@2028}  size = 18
"org.springframework.boot.SpringApplicationRunListener" -> {LinkedList@2030}  size = 1
"org.springframework.boot.env.PropertySourceLoader" -> {LinkedList@2032}  size = 2
"org.springframework.boot.diagnostics.FailureAnalysisReporter" -> {LinkedList@2034}  size = 1
"org.springframework.boot.SpringBootExceptionReporter" -> {LinkedList@2036}  size = 1
"org.springframework.boot.autoconfigure.AutoConfigurationImportFilter" -> {LinkedList@2038}  size = 3
"org.springframework.boot.autoconfigure.AutoConfigurationImportListener" -> {LinkedList@2040}  size = 1
"org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider" -> {LinkedList@2042}  size = 5

獲取ApplicationContextInitializer.class的對象

0 = "org.springframework.boot.devtools.restart.RestartScopeInitializer"
1 = "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer"
2 = "org.springframework.boot.context.ContextIdApplicationContextInitializer"
3 = "org.springframework.boot.context.config.DelegatingApplicationContextInitializer"
4 = "org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer"
5 = "org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer"
6 = "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer"
7 = "org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener"

實例化實現了ApplicationContextInitializer接口的所有對象並排序

通過AnnotationAwareOrderComparator.sort(instances);進行排序

0 = {DelegatingApplicationContextInitializer@1914} 
1 = {SharedMetadataReaderFactoryContextInitializer@1933} 
2 = {ContextIdApplicationContextInitializer@1896} 
3 = {RestartScopeInitializer@1861} 
4 = {ConfigurationWarningsApplicationContextInitializer@1878} 
5 = {RSocketPortInfoApplicationContextInitializer@1931} 
6 = {ServerPortInfoApplicationContextInitializer@1932} 
7 = {ConditionEvaluationReportLoggingListener@1934}

保存ApplicationContextInitializer

SpringApplication.setInitializers(Collection> initializers)

實例化監聽器

獲取ApplicationListener接口對象

0 = "org.springframework.boot.devtools.restart.RestartApplicationListener"
1 = "org.springframework.boot.devtools.logger.DevToolsLogFactory.Listener"
2 = "org.springframework.boot.ClearCachesApplicationListener"
3 = "org.springframework.boot.builder.ParentContextCloserApplicationListener"
4 = "org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor"
5 = "org.springframework.boot.context.FileEncodingApplicationListener"
6 = "org.springframework.boot.context.config.AnsiOutputApplicationListener"
7 = "org.springframework.boot.context.config.ConfigFileApplicationListener"
8 = "org.springframework.boot.context.config.DelegatingApplicationListener"
9 = "org.springframework.boot.context.logging.ClasspathLoggingApplicationListener"
10 = "org.springframework.boot.context.logging.LoggingApplicationListener"
11 = "org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener"
12 = "org.springframework.boot.autoconfigure.BackgroundPreinitializer"

實例化並排序

0 = {RestartApplicationListener@2043} 
1 = {CloudFoundryVcapEnvironmentPostProcessor@2044} 
2 = {ConfigFileApplicationListener@2045} 
3 = {AnsiOutputApplicationListener@2046} 
4 = {LoggingApplicationListener@2047} 
5 = {ClasspathLoggingApplicationListener@2048} 
6 = {BackgroundPreinitializer@2049} 
7 = {DelegatingApplicationListener@2050} 
8 = {ParentContextCloserApplicationListener@2051} 
9 = {DevToolsLogFactory$Listener@2052} 
10 = {ClearCachesApplicationListener@2053} 
11 = {FileEncodingApplicationListener@2054} 
12 = {LiquibaseServiceLocatorApplicationListener@2055}

保存ApplicationListener

SpringApplication.setListeners(Collection> listeners)

推斷啓動類

即獲取main方法的所在類

try {
			StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
			for (StackTraceElement stackTraceElement : stackTrace) {
				if ("main".equals(stackTraceElement.getMethodName())) {
					return Class.forName(stackTraceElement.getClassName());
				}
			}
		}
		catch (ClassNotFoundException ex) {
			// Swallow and continue
		}
		return null;

啓動

調用run方法

啓動耗時監視

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

配置headless

默認爲true

private void configureHeadlessProperty() {
		System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
				System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
	}

配置SpringApplicationRunListeners

獲取實現SpringApplicationRunListeners的工廠對象

0 = {EventPublishingRunListener@1958} 

將監聽器放到SpringApplicationRunListeners中

實例化SpringApplicationRunListeners,並保存監聽器

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

啓動監聽器

循環啓動

目前只有一個監聽器:EventPublishingRunListener

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

EventPublishingRunListener觸發廣播ApplicationStartingEvent事件

	@Override
	public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}

獲取支持ApplicationStartingEvent事件的所有監聽器並緩存

0 = {LoggingApplicationListener@1805} 
1 = {BackgroundPreinitializer@1827} 
2 = {DelegatingApplicationListener@1828} 
3 = {LiquibaseServiceLocatorApplicationListener@1829} 

進行多播ApplicationStartingEvent

即循環調用支持ApplicationStartingEvent事件的監聽器

for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}

配置入參

包裝成DefaultApplicationArguments

	ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

準備環境變量

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

根據環境創建環境變量

private ConfigurableEnvironment getOrCreateEnvironment() {
		if (this.environment != null) {
			return this.environment;
		}
		switch (this.webApplicationType) {
		case SERVLET:
			return new StandardServletEnvironment();
		case REACTIVE:
			return new StandardReactiveWebEnvironment();
		default:
			return new StandardEnvironment();
		}
	}

配置單例的ConversionService

	public static ConversionService getSharedInstance() {
		ApplicationConversionService sharedInstance = ApplicationConversionService.sharedInstance;
		if (sharedInstance == null) {
			synchronized (ApplicationConversionService.class) {
				sharedInstance = ApplicationConversionService.sharedInstance;
				if (sharedInstance == null) {
					sharedInstance = new ApplicationConversionService();
					ApplicationConversionService.sharedInstance = sharedInstance;
				}
			}
		}
		return sharedInstance;
	}

配置Properties參數

protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
		MutablePropertySources sources = environment.getPropertySources();
		if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
			sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));
		}
		if (this.addCommandLineProperties && args.length > 0) {
			String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
			if (sources.contains(name)) {
				PropertySource<?> source = sources.get(name);
				CompositePropertySource composite = new CompositePropertySource(name);
				composite.addPropertySource(
						new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
				composite.addPropertySource(source);
				sources.replace(name, composite);
			}
			else {
				sources.addFirst(new SimpleCommandLinePropertySource(args));
			}
		}
	}

配置Profile

protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
		Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);
		profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
		environment.setActiveProfiles(StringUtils.toStringArray(profiles));
	}

附加額外參數

public static void attach(Environment environment) {
		Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
		MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
		PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
		if (attached != null && attached.getSource() != sources) {
			sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
			attached = null;
		}
		if (attached == null) {
			sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
					new SpringConfigurationPropertySources(sources)));
		}
	}

觸發ApplicationEnvironmentPreparedEvent廣播事件

	@Override
	public void environmentPrepared(ConfigurableEnvironment environment) {
		this.initialMulticaster
				.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
	}

獲取所有監聽此事件的監聽器

0 = {ConfigFileApplicationListener@2838} 
1 = {AnsiOutputApplicationListener@3747} 
2 = {LoggingApplicationListener@1805} 
3 = {ClasspathLoggingApplicationListener@3748} 
4 = {BackgroundPreinitializer@1827} 
5 = {DelegatingApplicationListener@1828} 
6 = {FileEncodingApplicationListener@3749} 

循環調用監聽此事件的監聽器,和前面解析步驟一致

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

監聽器

ConfigFileApplicationListener

  • 加載工廠類
0 = {SystemEnvironmentPropertySourceEnvironmentPostProcessor@2911} 
1 = {SpringApplicationJsonEnvironmentPostProcessor@2912} 
2 = {CloudFoundryVcapEnvironmentPostProcessor@2913} 
3 = {ConfigFileApplicationListener@2838} 
4 = {DebugAgentEnvironmentPostProcessor@2914} 

創建Binder,綁定環境變量和SpringApplication

protected void bindToSpringApplication(ConfigurableEnvironment environment) {
		try {
			Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
		}
		catch (Exception ex) {
			throw new IllegalStateException("Cannot bind to SpringApplication", ex);
		}
	}

解析已存在的環境變量

封裝結果保存在PropertySourcesPlaceholdersResolver

sources = {SpringConfigurationPropertySources@3220} 
 sources = {MutablePropertySources@3206} "[ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, StubPropertySource {name='servletConfigInitParams'}, StubPropertySource {name='servletContextInitParams'}, PropertiesPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}]"
  propertySourceList = {CopyOnWriteArrayList@3241}  size = 7
   0 = {ConfigurationPropertySourcesPropertySource@3212} "ConfigurationPropertySourcesPropertySource {name='configurationProperties'}"
   1 = {PropertySource$StubPropertySource@3243} "StubPropertySource {name='servletConfigInitParams'}"
   2 = {PropertySource$StubPropertySource@3244} "StubPropertySource {name='servletContextInitParams'}"
   3 = {PropertiesPropertySource@3245} "PropertiesPropertySource {name='systemProperties'}"
   4 = {SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@3246} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
   5 = {RandomValuePropertySource@3247} "RandomValuePropertySource {name='random'}"
   6 = {OriginTrackedMapPropertySource@3248} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}"
 cache = {ConcurrentReferenceHashMap@3308}  size = 4
  {RandomValuePropertySource@3247} "RandomValuePropertySource {name='random'}" -> {SpringConfigurationPropertySource@3318} "RandomValuePropertySource {name='random'}"
  {SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@3246} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}" -> {SpringIterableConfigurationPropertySource@3319} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
  {PropertiesPropertySource@3245} "PropertiesPropertySource {name='systemProperties'}" -> {SpringIterableConfigurationPropertySource@3320} "PropertiesPropertySource {name='systemProperties'}"
  {OriginTrackedMapPropertySource@3248} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}" -> {SpringIterableConfigurationPropertySource@3321} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}"

綁定

protected void bindToSpringApplication(ConfigurableEnvironment environment) {
		try {
			Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
		}
		catch (Exception ex) {
			throw new IllegalStateException("Cannot bind to SpringApplication", ex);
		}
	}

重新設置"configurationProperties"

0 = {ConfigurationPropertySourcesPropertySource@3492} "ConfigurationPropertySourcesPropertySource {name='configurationProperties'}"
 logger = {LogAdapter$Slf4jLocationAwareLog@3505} 
 name = "configurationProperties"
 source = {SpringConfigurationPropertySources@3493} 
  sources = {MutablePropertySources@3402} "[ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, StubPropertySource {name='servletConfigInitParams'}, StubPropertySource {name='servletContextInitParams'}, PropertiesPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}]"
   propertySourceList = {CopyOnWriteArrayList@3406}  size = 7
    0 = {ConfigurationPropertySourcesPropertySource@3492} "ConfigurationPropertySourcesPropertySource {name='configurationProperties'}"
    1 = {PropertySource$StubPropertySource@3409} "StubPropertySource {name='servletConfigInitParams'}"
    2 = {PropertySource$StubPropertySource@3410} "StubPropertySource {name='servletContextInitParams'}"
    3 = {PropertiesPropertySource@3411} "PropertiesPropertySource {name='systemProperties'}"
    4 = {SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@3412} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
    5 = {RandomValuePropertySource@3413} "RandomValuePropertySource {name='random'}"
    6 = {OriginTrackedMapPropertySource@3414} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}"
  cache = {ConcurrentReferenceHashMap@3494}  size = 0
1 = {PropertySource$StubPropertySource@3409} "StubPropertySource {name='servletConfigInitParams'}"
2 = {PropertySource$StubPropertySource@3410} "StubPropertySource {name='servletContextInitParams'}"
3 = {PropertiesPropertySource@3411} "PropertiesPropertySource {name='systemProperties'}"
4 = {SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@3412} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
5 = {RandomValuePropertySource@3413} "RandomValuePropertySource {name='random'}"
6 = {OriginTrackedMapPropertySource@3414} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}"

配置忽略Bean信息

	private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
		if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
			Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
			System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
		}
	}

打印Banner

private Banner printBanner(ConfigurableEnvironment environment) {
		if (this.bannerMode == Banner.Mode.OFF) {
			return null;
		}
		ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
				: new DefaultResourceLoader(getClassLoader());
		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);
	}

默認的Banner:SpringBootBanner

	public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
		for (String line : BANNER) {
			printStream.println(line);
		}
		String version = SpringBootVersion.getVersion();
		version = (version != null) ? " (v" + version + ")" : "";
		StringBuilder padding = new StringBuilder();
		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();
	}

創建上下文

根據類型實例化上下文

WEB默認情況下是AnnotationConfigServletWebServerApplicationContext,然後實例化。

protected ConfigurableApplicationContext createApplicationContext() {
		Class<?> contextClass = this.applicationContextClass;
		if (contextClass == null) {
			try {
				switch (this.webApplicationType) {
				case SERVLET:
					contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
					break;
				case REACTIVE:
					contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
					break;
				default:
					contextClass = Class.forName("org.springframework.context."
			+ "annotation.AnnotationConfigApplicationContext");
				}
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
			}
		}
		return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
	}
  • 父類通用上下文:GenericApplicationContext

這裏會實例化DefaultListableBeanFactory並保存在beanFactory屬性中,後續都會基於它進行操作

public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

簡略版繼承關係:

AnnotationConfigServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
GenericWebApplicationContext (org.springframework.web.context.support)
GenericApplicationContext (org.springframework.context.support)

  • 實例化AnnotatedBeanDefinitionReader
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
		this(registry, getOrCreateEnvironment(registry));
	}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    this.registry = registry;
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
  • 註冊AnnotationConfigProcessors
		// 獲取上下文,即上文提到的GenericApplicationContext#beanFactory

		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				// Order比較器
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				// 自動轉入
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
		
		// org.springframework.context.annotation.internalConfigurationAnnotationProcessor
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			// @Configuration類的引導處理的BeanFactoryPostProcessor
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		// org.springframework.context.annotation.internalAutowiredAnnotationProcessor
		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			// @Autowired @Value @Inject 等自動注入相關注解的處理類
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// org.springframework.context.annotation.internalCommonAnnotationProcessor
		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			// 支持普通的Java開箱即用註釋,也支持JSR-250註釋
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// jpa 功能支持 PersistenceAnnotationBeanPostProcessor.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		
		// org.springframework.context.event.internalEventListenerProcessor
		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
            // 事件監聽器
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}
		// org.springframework.context.event.internalEventListenerFactory
		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
			// 事件監聽工廠
            RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}

  • 實例化類掃描器ClassPathBeanDefinitionScanner

一個bean定義掃描器,它檢測類路徑上的bean候選,在給定的註冊表(BeanFactory或ApplicationContext)中註冊相應的bean定義,通過可配置的類型篩選器檢測候選類,Bean條件過濾在這裏做的。

 * {@link org.springframework.stereotype.Component @Component},
 * {@link org.springframework.stereotype.Repository @Repository},
 * {@link org.springframework.stereotype.Service @Service}, or
 * {@link org.springframework.stereotype.Controller @Controller} stereotype.
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
    this(registry, true);
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
    this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}
  • 添加默認過濾器
protected void registerDefaultFilters() {
		this.includeFilters.add(new AnnotationTypeFilter(Component.class));
		ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
		try {
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
			logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
		}
		catch (ClassNotFoundException ex) {
			// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
		}
		try {
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
			logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

獲取SpringFactory實例SpringBootExceptionReporter

獲取所有SpringBootExceptionReporter對象並實例化

用於觸發從spring.factories加載的FailureAnalyzer和FailureAnalysisReporter實例的實用程序。 需要訪問BeanFactory來執行分析的故障分析器可以實現BeanFactoryAware,以便在調用故障分析器.analyze(Throwable)之前注入BeanFactory

org.springframework.boot.diagnostics.FailureAnalyzers

準備上下文

把之前加載的監聽器,啓動參數,環境變量放到上下文中

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);
		}
		// Add boot specific singleton beans
		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());
		}
		// Load the sources
		Set<Object> sources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		load(context, sources.toArray(new Object[0]));
		listeners.contextLoaded(context);
	}

應用初始化

  • 獲取之前的Initializer對象
0 = {DelegatingApplicationContextInitializer@3540} 
1 = {SharedMetadataReaderFactoryContextInitializer@3541} 
2 = {ContextIdApplicationContextInitializer@3542} 
3 = {ConfigurationWarningsApplicationContextInitializer@3543} 
4 = {RSocketPortInfoApplicationContextInitializer@3544} 
5 = {ServerPortInfoApplicationContextInitializer@3545} 
6 = {ConditionEvaluationReportLoggingListener@3546} 
  • Initializer如果實現了ApplicationContextInitializer接口,那麼回調設置上下文
protected void applyInitializers(ConfigurableApplicationContext context) {
		for (ApplicationContextInitializer initializer : getInitializers()) {
			Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
					ApplicationContextInitializer.class);
			Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
			initializer.initialize(context);
		}
	}

觸發contextPrepared事件ApplicationContextInitializedEvent

監聽該事件的監聽器

0 = {BackgroundPreinitializer@3824} 
1 = {DelegatingApplicationListener@3831} 

打印啓動信息

new StartupInfoLogger(this.mainApplicationClass).logStarting(getApplicationLog());

void logStarting(Log applicationLog) {
		Assert.notNull(applicationLog, "Log must not be null");
		applicationLog.info(LogMessage.of(this::getStartingMessage));
		applicationLog.debug(LogMessage.of(this::getRunningMessage));
	}
private CharSequence getStartingMessage() {
    StringBuilder message = new StringBuilder();
    message.append("Starting ");
    appendApplicationName(message);
    appendVersion(message, this.sourceClass);
    appendOn(message);
    appendPid(message);
    appendContext(message);
    return message;
}

StartingMessage: info

2020-04-16 11:22:38.085  INFO 17884 --- [           main] c.e.factory.app.FactoryDemoApplication   : Starting FactoryDemoApplication on Ccx with PID 17884 (E:\IDEA\ccxxx\factory-demo\target\classes started by cx521 in E:\IDEA\ccxxx)

RunningMessage: debug

2020-04-16 11:26:52.314 DEBUG 17884 --- [           main] c.e.factory.app.FactoryDemoApplication   : Running with Spring Boot v2.2.2.RELEASE, Spring v5.2.2.RELEASE

打印當前環境:

protected void logStartupProfileInfo(ConfigurableApplicationContext context) {
		Log log = getApplicationLog();
		if (log.isInfoEnabled()) {
			String[] activeProfiles = context.getEnvironment().getActiveProfiles();
			if (ObjectUtils.isEmpty(activeProfiles)) {
				String[] defaultProfiles = context.getEnvironment().getDefaultProfiles();
				log.info("No active profile set, falling back to default profiles: "
						+ StringUtils.arrayToCommaDelimitedString(defaultProfiles));
			}
			else {
				log.info("The following profiles are active: "
						+ StringUtils.arrayToCommaDelimitedString(activeProfiles));
			}
		}
	}
2020-04-16 11:28:14.143  INFO 17884 --- [           main] c.e.factory.app.FactoryDemoApplication   : No active profile set, falling back to default profiles: default

添加一些額外的Bean支持

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

設置BeanDefinitionLoader

  • 設置各種資源加載器
	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 = new XmlBeanDefinitionReader(registry);
		if (isGroovyPresent()) {
			this.groovyReader = new GroovyBeanDefinitionReader(registry);
		}
		this.scanner = new ClassPathBeanDefinitionScanner(registry);
		this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
	}
  • 調用load方法進行加載
// sources爲啓動類
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();
	}

觸發contextLoaded事件

  • 獲取所有監聽事件
0 = {CloudFoundryVcapEnvironmentPostProcessor@4378} 
1 = {ConfigFileApplicationListener@3859} 
2 = {AnsiOutputApplicationListener@3860} 
3 = {LoggingApplicationListener@3861} 
4 = {ClasspathLoggingApplicationListener@3862} 
5 = {BackgroundPreinitializer@3824} 
6 = {DelegatingApplicationListener@3831} 
7 = {ParentContextCloserApplicationListener@4379} 
8 = {ClearCachesApplicationListener@4380} 
9 = {FileEncodingApplicationListener@3863} 
10 = {LiquibaseServiceLocatorApplicationListener@4381} 
  • 將監聽器添加到上下文中,如果實現了ApplicationContextAware接口的會進行上下文回調。
	public void contextLoaded(ConfigurableApplicationContext context) {
		for (ApplicationListener<?> listener : this.application.getListeners()) {
			if (listener instanceof ApplicationContextAware) {
				((ApplicationContextAware) listener).setApplicationContext(context);
			}
			context.addApplicationListener(listener);
		}
		this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
	}

觸發ApplicationPreparedEvent事件

進行數據回調

0 = {CloudFoundryVcapEnvironmentPostProcessor@3657} 
1 = {ConfigFileApplicationListener@3675} 
2 = {LoggingApplicationListener@3676} 
3 = {BackgroundPreinitializer@3365} 
4 = {DelegatingApplicationListener@3381} 

刷新上下文

spring的標準流程,spring啓動

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.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				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.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				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.
				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();
			}
		}
	}

準備刷新 prepareRefresh

清空緩存,這裏有2個回調,模板方法都是空實現

	protected void prepareRefresh() {
		// Switch to active.
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment.
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

earlyApplicationListeners列表

0 = {RSocketPortInfoApplicationContextInitializer$Listener@3716} 
1 = {ServerPortInfoApplicationContextInitializer@3717} 
2 = {ConditionEvaluationReportLoggingListener$ConditionEvaluationReportListener@3718} 
3 = {CloudFoundryVcapEnvironmentPostProcessor@3719} 
4 = {ConfigFileApplicationListener@3720} 
5 = {AnsiOutputApplicationListener@3721} 
6 = {LoggingApplicationListener@3722} 
7 = {ClasspathLoggingApplicationListener@3723} 
8 = {BackgroundPreinitializer@3724} 
9 = {DelegatingApplicationListener@3725} 
10 = {ParentContextCloserApplicationListener@3726} 
11 = {ClearCachesApplicationListener@3727} 
12 = {FileEncodingApplicationListener@3728} 
13 = {LiquibaseServiceLocatorApplicationListener@3729} 

獲取工廠obtainFreshBeanFactory

調用GenericApplicationContext獲取BeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		return getBeanFactory();
	}

準備一些初始化信息prepareBeanFactory

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
        // BeanExpressionResolver接口的標準實現,Spring EL解析,ex: #{beanName}
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        //填充給定PropertyEditorRegistry(通常是org.springframe .bean)的PropertyEditorRegistry實現。
        //用於在帶有資源編輯器的org.springframework.context. context中創建bean的BeanWrapper。
        //由org.springframework.context.support.AbstractApplicationContext使用
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// 配置工廠回調
        // BeanPostProcessor實現供應ApplicationContext,環境,或StringValueResolver 
        //ApplicationContext EnvironmentAware bean實現,EmbeddedValueResolverAware, ResourceLoaderAware, 
        // ApplicationEventPublisherAware MessageSourceAware和/或ApplicationContextAware接口。 
        //實現的接口按照上面提到的順序被滿足。 應用程序上下文將自動將其註冊到它們的底層bean工廠。應用程序不直接使用它。
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        // 忽略給定的自動裝配依賴接口,由系統自動調用
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

		// 將系統Bean加入到容器中,我們可以在系統通過注入的方式獲取
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// 將早期的後處理器註冊爲application監聽器,用於檢測內部bean。
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// 註冊環境變量相關Bean
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}
		

調用工廠中的處理器

Spiring 將BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor區分開調用:

BeanDefinitionRegistryPostProcessor實現自BeanFactoryPostProcessor,因此需要2步:

1.void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

2.void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

單獨BeanFactoryPostProcessor接口:

1.void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}
  • 先處理內部的BeanFactoryPostProcessor,保存在AbstractApplicationContext.beanFactoryPostProcessors中:
0 = {SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor@4139} 
1 = {ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor@4140} 
2 = {ConfigFileApplicationListener$PropertySourceOrderingPostProcessor@4141} 

BeanDefinitionRegistryPostProcessor 實現自 BeanFactoryPostProcessor接口,調用前需要先調用BeanDefinitionRegistryPostProcessor 的postProcessBeanDefinitionRegistry接口,

	for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}
  • 實現PriorityOrdered接口的BeanDefinitionRegistryPostProcessor:

currentRegistryProcessors保存從上下文中獲取到實現PriorityOrdered接口的實例;

postProcessorNames保存的是beanName;

List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
Set<String> processedBeans = new HashSet<>();
String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				// 注意這裏類型過濾爲 PriorityOrdered.class
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 將容器中獲取的processor添加到registryProcessors中
registryProcessors.addAll(currentRegistryProcessors);
// 循環調用新加的processor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 清空臨時列表
currentRegistryProcessors.clear();

循環調用新加的processor:

這裏新加的是org.springframework.context.annotation.ConfigurationClassPostProcessor

private static void invokeBeanDefinitionRegistryPostProcessors(
      Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

   for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
      postProcessor.postProcessBeanDefinitionRegistry(registry);
   }
}
  • 實現Ordered接口的BeanFactoryPostProcessor:

currentRegistryProcessors保存從上下文中獲取到實現Ordered接口的實例;

postProcessorNames保存的是beanName;

	postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				// 注意這裏類型過濾爲 Ordered.class,且postProcessorName不存在,防止重複調用
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
            // 排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            // 將容器中獲取的processor添加到registryProcessors中
            registryProcessors.addAll(currentRegistryProcessors);
            // 循環調用新加的processor
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // 清空臨時列表
            currentRegistryProcessors.clear();
  • 處理剩下無序的processor:
boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					// postProcessorName不存在的,防止重複調用
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
  			// 排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            // 將容器中獲取的processor添加到registryProcessors中
            registryProcessors.addAll(currentRegistryProcessors);
            // 循環調用新加的processor
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // 清空臨時列表
            currentRegistryProcessors.clear();
  • 調用postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

    循環實現了BeanDefinitionRegistryPostProcessor接口的實例.

// 實現了BeanDefinitionRegistryPostProcessor的接口
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 只實現了BeanFactoryPostProcessor的接口
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

private static void invokeBeanFactoryPostProcessors(
      Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

   for (BeanFactoryPostProcessor postProcessor : postProcessors) {
      postProcessor.postProcessBeanFactory(beanFactory);
   }
}
  • 獲取容器中只實現了BeanFactoryPostProcessors的處理器,注意和前邊步驟BeanDefinitionRegistryPostProcessor區分開,前邊是需要兩步操作:

    1.void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

    2.void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			// 這裏排除了已經處理過的processor
			if (processedBeans.contains(ppName)) {
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}
		
		// 首先調用實現了PriorityOrdered接口的
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// 然後實現了Ordered接口的
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// 調用無須的
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// 清空源信息
		beanFactory.clearMetadataCache();

初始化國際化

	protected void initMessageSource() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
			this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
			// Make MessageSource aware of parent MessageSource.
			if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
				HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
				if (hms.getParentMessageSource() == null) {
					// Only set parent context as parent MessageSource if no parent MessageSource
					// registered already.
					hms.setParentMessageSource(getInternalParentMessageSource());
				}
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Using MessageSource [" + this.messageSource + "]");
			}
		}
		else {
			// Use empty MessageSource to be able to accept getMessage calls.
			// 默認實現
			DelegatingMessageSource dms = new DelegatingMessageSource();
			dms.setParentMessageSource(getInternalParentMessageSource());
			this.messageSource = dms;
			beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
			if (logger.isTraceEnabled()) {
				logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
			}
		}
	}

初始化事件廣播器

protected void initApplicationEventMulticaster() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isTraceEnabled()) {
				logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
            // 默認的廣播實例
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
			if (logger.isTraceEnabled()) {
				logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
						"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
			}
		}
	}

刷新

protected void onRefresh() {
    // 調用的是GenericWebApplicationContext.onRefresh();
   super.onRefresh();
   try {
       // 創建WebServer
      createWebServer();
   }
   catch (Throwable ex) {
      throw new ApplicationContextException("Unable to start web server", ex);
   }
}
// 是GenericWebApplicationContext.onRefresh
protected void onRefresh() {
    // 初始化主題
    this.themeSource = UiApplicationContextUtils.initThemeSource(this);
}

創建Web服務(Tomcat啓動)

調用ServletWebServerApplicationContext的createWebServer方法

private void createWebServer() {
		// 啓動時爲null
		WebServer webServer = this.webServer;
		// 啓動時爲null
		ServletContext servletContext = getServletContext();
		if (webServer == null && servletContext == null) {
			ServletWebServerFactory factory = getWebServerFactory();
			this.webServer = factory.getWebServer(getSelfInitializer());
		}
		else if (servletContext != null) {
			try {
				getSelfInitializer().onStartup(servletContext);
			}
			catch (ServletException ex) {
				throw new ApplicationContextException("Cannot initialize servlet context", ex);
			}
		}
		initPropertySources();
	}
	
    protected ServletWebServerFactory getWebServerFactory() {
    // Use bean names so that we don't consider the hierarchy
    // 這裏會獲取到tomcatServletWebServerFactory
    String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
    if (beanNames.length == 0) {
    throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
    + "ServletWebServerFactory bean.");
    }
    if (beanNames.length > 1) {
    throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
    + "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
    }
    return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
    }
獲取Tomcat 服務

TomcatServletWebServerFactory#getWebServer

public WebServer getWebServer(ServletContextInitializer... initializers) {
    	if (this.disableMBeanRegistry) {
            // 默認禁用MBean註冊
			Registry.disableRegistry();
		}
		Tomcat tomcat = new Tomcat();
    	// 創建了一個臨時目錄,ex: C:\Users\cx521\AppData\Local\Temp\tomcat.5544330150298139628.8080
		File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
    	// 設置Tomcat基本路徑
		tomcat.setBaseDir(baseDir.getAbsolutePath());
    	// 創建連接
		Connector connector = new Connector(this.protocol);
    	// 啓動失敗時拋出異常
		connector.setThrowOnFailure(true);
		tomcat.getService().addConnector(connector);
    	// 自定義連接信息
		customizeConnector(connector);
		tomcat.setConnector(connector);
    	// 自動部署
		tomcat.getHost().setAutoDeploy(false);
    	// 配置引擎
		configureEngine(tomcat.getEngine());
		for (Connector additionalConnector : this.additionalTomcatConnectors) {
			tomcat.getService().addConnector(additionalConnector);
		}
    	// 準備環境
		prepareContext(tomcat.getHost(), initializers);
    	// 啓動在這裏進行.new TomcatWebServer(tomcat, getPort() >= 0);
		return getTomcatWebServer(tomcat);
	}

// 臨時目錄名爲tomcat.端口形式
protected final File createTempDir(String prefix) {
    File tempDir = File.createTempFile(prefix + ".", "." + getPort());
    tempDir.delete();
    tempDir.mkdir();
    tempDir.deleteOnExit();
    return tempDir;
}

// 自定義連接
protected void customizeConnector(Connector connector) {
    	// 設置端口
		int port = Math.max(getPort(), 0);
		connector.setPort(port);
		if (StringUtils.hasText(this.getServerHeader())) {
			connector.setAttribute("server", this.getServerHeader());
		}
		if (connector.getProtocolHandler() instanceof AbstractProtocol) {
            // 自定義協議
			customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler());
		}
    	// 自定義協議處理器,默認爲Http11NioProtocol
		invokeProtocolHandlerCustomizers(connector.getProtocolHandler());
		if (getUriEncoding() != null) {
            // 設置編碼爲UTF-8
			connector.setURIEncoding(getUriEncoding().name());
		}
		// 延遲綁定
		connector.setProperty("bindOnInit", "false");
    	// 設置ssl,https相關
		if (getSsl() != null && getSsl().isEnabled()) {
			customizeSsl(connector);
		}
    	// 設置壓縮,最小響應包大小爲2048B
		TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(getCompression());
		compression.customize(connector);
    	// 添加 其他的自定義屬性,比如TomcatWebServerFactoryCustomizer#customize中定義的
		for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
			customizer.customize(connector);
		}
	}

// 準備上下文
protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
		File documentRoot = getValidDocumentRoot();
		TomcatEmbeddedContext context = new TomcatEmbeddedContext();
		if (documentRoot != null) {
			context.setResources(new LoaderHidingResourceRoot(context));
		}
    	// 設置名稱
		context.setName(getContextPath());
    	// 名字
		context.setDisplayName(getDisplayName());
    	// 路徑
		context.setPath(getContextPath());
    	// 創建文檔路徑, ex: C:\Users\cx521\AppData\Local\Temp\tomcat-docbase.4781687470030327872.8080
		File docBase = (documentRoot != null) ? documentRoot : createTempDir("tomcat-docbase");
		context.setDocBase(docBase.getAbsolutePath());
    	// 設置監聽器 上下文中的start()方法將把“configured”設置爲false,並期望偵聽器將其設置回true
		context.addLifecycleListener(new FixContextListener());
    	// 類加載器
		context.setParentClassLoader((this.resourceLoader != null) ? this.resourceLoader.getClassLoader()
				: ClassUtils.getDefaultClassLoader());
    	// 重置默認的映射
		resetDefaultLocaleMapping(context);
    	// 添加本地映射,HttpEncodingAutoConfiguration會去設置
		addLocaleMappings(context);
		context.setUseRelativeRedirects(false);
		try {
			context.setCreateUploadTargets(true);
		}
		catch (NoSuchMethodError ex) {
			// Tomcat is < 8.5.39. Continue.
		}
    	// 配置跳過指定jar過濾器表達式
		configureTldSkipPatterns(context);
		WebappLoader loader = new WebappLoader(context.getParentClassLoader());
		loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName());
		loader.setDelegate(true);
		context.setLoader(loader);
    	// 添加默認的Servlet
		if (isRegisterDefaultServlet()) {
			addDefaultServlet(context);
		}
    	// 添加JspServlet
		if (shouldRegisterJspServlet()) {
			addJspServlet(context);
			addJasperInitializer(context);
		}
		context.addLifecycleListener(new StaticResourceConfigurer(context));
		ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
		host.addChild(context);
    	// 配置上下文
		configureContext(context, initializersToUse);
		postProcessContext(context);
	}

protected void configureContext(Context context, ServletContextInitializer[] initializers) {
		TomcatStarter starter = new TomcatStarter(initializers);
		if (context instanceof TomcatEmbeddedContext) {
            // 嵌入式上下文環境
			TomcatEmbeddedContext embeddedContext = (TomcatEmbeddedContext) context;
			embeddedContext.setStarter(starter);
			embeddedContext.setFailCtxIfServletStartFails(true);
		}
		context.addServletContainerInitializer(starter, NO_CLASSES);
		for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) {
			context.addLifecycleListener(lifecycleListener);
		}
		for (Valve valve : this.contextValves) {
			context.getPipeline().addValve(valve);
		}
    	// 設置異常頁面
		for (ErrorPage errorPage : getErrorPages()) {
			org.apache.tomcat.util.descriptor.web.ErrorPage tomcatErrorPage = new org.apache.tomcat.util.descriptor.web.ErrorPage();
			tomcatErrorPage.setLocation(errorPage.getPath());
			tomcatErrorPage.setErrorCode(errorPage.getStatusCode());
			tomcatErrorPage.setExceptionType(errorPage.getExceptionName());
			context.addErrorPage(tomcatErrorPage);
		}
    	// 設置mime映射
		for (MimeMappings.Mapping mapping : getMimeMappings()) {
			context.addMimeMapping(mapping.getExtension(), mapping.getMimeType());
		}
		configureSession(context);
		new DisableReferenceClearingContextCustomizer().customize(context);
		for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {
			customizer.customize(context);
		}
	}

Http11NioProtocol的屬性:

compressionConfig = {CompressionConfig@13417} 
 compressionLevel = 0
 noCompressionUserAgents = null
 compressibleMimeType = "text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json,application/xml"
 compressibleMimeTypes = null
 compressionMinSize = 2048
useKeepAliveResponseHeader = true
relaxedPathChars = null
relaxedQueryChars = null
allowHostHeaderMismatch = false
rejectIllegalHeaderName = true
maxSavePostSize = 4096
maxHttpHeaderSize = 8192
connectionUploadTimeout = 300000
disableUploadTimeout = true
restrictedUserAgents = null
server = null
serverRemoveAppProvidedValues = false
maxTrailerSize = 8192
maxExtensionSize = 8192
maxSwallowSize = 2097152
secure = false
allowedTrailerHeaders = {Collections$SetFromMap@13418}  size = 0
upgradeProtocols = {ArrayList@13419}  size = 0
httpUpgradeProtocols = {HashMap@13420}  size = 0
negotiatedProtocols = {HashMap@13421}  size = 0
defaultSSLHostConfig = null
rgOname = null
nameIndex = 1
endpoint = {NioEndpoint@13422} 
handler = {AbstractProtocol$ConnectionHandler@13423} 
 proto = {Http11NioProtocol@13347} 
 global = {RequestGroupInfo@13437} "BaseModelMbean[null]"
 registerCount = {AtomicLong@13438} "0"
 recycledProcessors = {AbstractProtocol$RecycledProcessors@13439} 
waitingProcessors = {Collections$SetFromMap@13424}  size = 0
timeoutFuture = null
monitorFuture = null
adapter = null
processorCache = 200
clientCertProvider = null
maxHeaderCount = 100
domain = null
oname = null
mserver = null

自定義的屬性TomcatWebServerFactoryCustomizer#customize

	@Override
	public void customize(ConfigurableTomcatWebServerFactory factory) {
		ServerProperties properties = this.serverProperties;
		ServerProperties.Tomcat tomcatProperties = properties.getTomcat();
		PropertyMapper propertyMapper = PropertyMapper.get();
		propertyMapper.from(tomcatProperties::getBasedir).whenNonNull().to(factory::setBaseDirectory);
		propertyMapper.from(tomcatProperties::getBackgroundProcessorDelay).whenNonNull().as(Duration::getSeconds)
				.as(Long::intValue).to(factory::setBackgroundProcessorDelay);
		customizeRemoteIpValve(factory);
		propertyMapper.from(tomcatProperties::getMaxThreads).when(this::isPositive)
				.to((maxThreads) -> customizeMaxThreads(factory, tomcatProperties.getMaxThreads()));
		propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive)
				.to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads));
		propertyMapper.from(this::determineMaxHttpHeaderSize).whenNonNull().asInt(DataSize::toBytes)
				.when(this::isPositive)
				.to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory, maxHttpHeaderSize));
		propertyMapper.from(tomcatProperties::getMaxSwallowSize).whenNonNull().asInt(DataSize::toBytes)
				.to((maxSwallowSize) -> customizeMaxSwallowSize(factory, maxSwallowSize));
		propertyMapper.from(tomcatProperties::getMaxHttpPostSize).asInt(DataSize::toBytes)
				.when((maxHttpPostSize) -> maxHttpPostSize != 0)
				.to((maxHttpPostSize) -> customizeMaxHttpPostSize(factory, maxHttpPostSize));
		propertyMapper.from(tomcatProperties::getAccesslog).when(ServerProperties.Tomcat.Accesslog::isEnabled)
				.to((enabled) -> customizeAccessLog(factory));
		propertyMapper.from(tomcatProperties::getUriEncoding).whenNonNull().to(factory::setUriEncoding);
		propertyMapper.from(properties::getConnectionTimeout).whenNonNull()
				.to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout));
		propertyMapper.from(tomcatProperties::getMaxConnections).when(this::isPositive)
				.to((maxConnections) -> customizeMaxConnections(factory, maxConnections));
		propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive)
				.to((acceptCount) -> customizeAcceptCount(factory, acceptCount));
		customizeStaticResources(factory);
		customizeErrorReportValve(properties.getError(), factory);
	}

跳過指定jar

0 = "ant-*.jar"
1 = "aspectj*.jar"
2 = "commons-beanutils*.jar"
3 = "commons-codec*.jar"
4 = "commons-collections*.jar"
5 = "commons-dbcp*.jar"
6 = "commons-digester*.jar"
7 = "commons-fileupload*.jar"
8 = "commons-httpclient*.jar"
9 = "commons-io*.jar"
10 = "commons-lang*.jar"
11 = "commons-logging*.jar"
12 = "commons-math*.jar"
13 = "commons-pool*.jar"
14 = "geronimo-spec-jaxrpc*.jar"
15 = "h2*.jar"
16 = "hamcrest*.jar"
17 = "hibernate*.jar"
18 = "jaxb-runtime-*.jar"
19 = "jmx*.jar"
20 = "jmx-tools-*.jar"
21 = "jta*.jar"
22 = "junit-*.jar"
23 = "httpclient*.jar"
24 = "log4j-*.jar"
25 = "mail*.jar"
26 = "org.hamcrest*.jar"
27 = "slf4j*.jar"
28 = "tomcat-embed-core-*.jar"
29 = "tomcat-embed-logging-*.jar"
30 = "tomcat-jdbc-*.jar"
31 = "tomcat-juli-*.jar"
32 = "tools.jar"
33 = "wsdl4j*.jar"
34 = "xercesImpl-*.jar"
35 = "xmlParserAPIs-*.jar"
36 = "xml-apis-*.jar"
37 = "antlr-*.jar"
38 = "aopalliance-*.jar"
39 = "aspectjrt-*.jar"
40 = "aspectjweaver-*.jar"
41 = "classmate-*.jar"
42 = "dom4j-*.jar"
43 = "ecj-*.jar"
44 = "ehcache-core-*.jar"
45 = "hibernate-core-*.jar"
46 = "hibernate-commons-annotations-*.jar"
47 = "hibernate-entitymanager-*.jar"
48 = "hibernate-jpa-2.1-api-*.jar"
49 = "hibernate-validator-*.jar"
50 = "hsqldb-*.jar"
51 = "jackson-annotations-*.jar"
52 = "jackson-core-*.jar"
53 = "jackson-databind-*.jar"
54 = "jandex-*.jar"
55 = "javassist-*.jar"
56 = "jboss-logging-*.jar"
57 = "jboss-transaction-api_*.jar"
58 = "jcl-over-slf4j-*.jar"
59 = "jdom-*.jar"
60 = "jul-to-slf4j-*.jar"
61 = "log4j-over-slf4j-*.jar"
62 = "logback-classic-*.jar"
63 = "logback-core-*.jar"
64 = "rome-*.jar"
65 = "slf4j-api-*.jar"
66 = "spring-aop-*.jar"
67 = "spring-aspects-*.jar"
68 = "spring-beans-*.jar"
69 = "spring-boot-*.jar"
70 = "spring-core-*.jar"
71 = "spring-context-*.jar"
72 = "spring-data-*.jar"
73 = "spring-expression-*.jar"
74 = "spring-jdbc-*.jar,"
75 = "spring-orm-*.jar"
76 = "spring-oxm-*.jar"
77 = "spring-tx-*.jar"
78 = "snakeyaml-*.jar"
79 = "tomcat-embed-el-*.jar"
80 = "validation-api-*.jar"
啓動Tomcat(TomcatWebServer#initialize)
	private void initialize() throws WebServerException {
		logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
		synchronized (this.monitor) {
			try {
				addInstanceIdToEngineName();
				// StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]
				Context context = findContext();
				context.addLifecycleListener((event) -> {
					if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
						// Remove service connectors so that protocol binding doesn't
						// happen when the service is started.
						removeServiceConnectors();
					}
				});

				// 啓動服務器以觸發初始化監聽器
				this.tomcat.start();

				// We can re-throw failure exception directly in the main thread
				rethrowDeferredStartupExceptions();

				try {
					ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
				}
				catch (NamingException ex) {
					// Naming is not enabled. Continue
				}

				// Unlike Jetty, all Tomcat threads are daemon threads. We create a
				// blocking non-daemon to stop immediate shutdown
				startDaemonAwaitThread();
			}
			catch (Exception ex) {
				stopSilently();
				destroySilently();
				throw new WebServerException("Unable to start embedded Tomcat", ex);
			}
		}
	}

初始化資源

@Override
	public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
		WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
	}

註冊監聽器

  • 存放在SimpleApplicationEventMulticaster#defaultRetriever
protected void registerListeners() {
		// 首先註冊靜態指定的偵聽器。
		for (ApplicationListener<?> listener : getApplicationListeners()) {
            // 工廠自帶的監聽器需要檢查下是否被代理,有的話需要去除
			getApplicationEventMulticaster().addApplicationListener(listener);
		}

	}

public void addApplicationListener(ApplicationListener<?> listener) {
		synchronized (this.retrievalMutex) {
			// 如果已經註冊,則顯式刪除代理的目標,以避免對同一偵聽器的重複調用。
			Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
			if (singletonTarget instanceof ApplicationListener) {
				// 刪除
				this.defaultRetriever.applicationListeners.remove(singletonTarget);
			}
			this.defaultRetriever.applicationListeners.add(listener);
			this.retrieverCache.clear();
		}
	}

工廠中自帶的ApplicationListener

0 = {RSocketPortInfoApplicationContextInitializer$Listener@29269} 
1 = {ServerPortInfoApplicationContextInitializer@29398} 
2 = {ConditionEvaluationReportLoggingListener$ConditionEvaluationReportListener@29399} 
3 = {CloudFoundryVcapEnvironmentPostProcessor@29400} 
4 = {ConfigFileApplicationListener@29401} 
5 = {AnsiOutputApplicationListener@29402} 
6 = {LoggingApplicationListener@29403} 
7 = {ClasspathLoggingApplicationListener@29404} 
8 = {BackgroundPreinitializer@29405} 
9 = {DelegatingApplicationListener@29406} 
10 = {ParentContextCloserApplicationListener@29407} 
11 = {ClearCachesApplicationListener@29408} 
12 = {FileEncodingApplicationListener@29409} 
13 = {LiquibaseServiceLocatorApplicationListener@29410} 
14 = {SharedMetadataReaderFactoryContextInitializer$SharedMetadataReaderFactoryBean@12087} 
  • 獲取容器註冊的監聽器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			// 直接添加
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}
		
public void addApplicationListenerBean(String listenerBeanName) {
		synchronized (this.retrievalMutex) {
			this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
			this.retrieverCache.clear();
		}
	}
  • 獲取早期的應用事件

    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    		this.earlyApplicationEvents = null;
    		if (earlyEventsToProcess != null) {
    			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
    				getApplicationEventMulticaster().multicastEvent(earlyEvent);
    			}
    		}
    

完成工廠初始化finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// 爲此上下文初始化轉換服務。
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

		// 設置凍結,允許緩存所有的bean定義元數據。
		beanFactory.freezeConfiguration();

		// 實例化所有非延遲加載的單例對象
		beanFactory.preInstantiateSingletons();
	}

完成刷新 finishRefresh

ServletWebServerApplicationContext#finishRefresh

@Override
	protected void finishRefresh() {
		super.finishRefresh();
		WebServer webServer = startWebServer();
		if (webServer != null) {
			publishEvent(new ServletWebServerInitializedEvent(webServer, this));
		}
	}
調用父類AbstractApplicationContext#finishRefresh
protected void finishRefresh() {
		// 清除上下文級的資源緩存(比如掃描的ASM元數據)。
		clearResourceCaches();

		// 爲此上下文初始化生命週期處理器。DefaultLifecycleProcessor
		initLifecycleProcessor();

		// 生命週期處理器開始運行.
		getLifecycleProcessor().onRefresh();

		// 推送PayloadApplicationEvent事件	
		publishEvent(new ContextRefreshedEvent(this));

		//註冊MBean.
		LiveBeansView.registerApplicationContext(this);
	}
發送ServletWebServerInitializedEvent事件
0 = {SpringApplicationAdminMXBeanRegistrar@30505} 
1 = {DelegatingApplicationListener@29406} 
2 = {ServerPortInfoApplicationContextInitializer@29398} 

清空元數據緩存resetCommonCaches

	protected void resetCommonCaches() {
		ReflectionUtils.clearCache();
		AnnotationUtils.clearCache();
		ResolvableType.clearCache();
		CachedIntrospectionResults.clearClassLoader(getClassLoader());
	}

註冊個關閉的勾子

在虛擬中註冊個勾子,以供關閉時能調用生命週期方法

public void registerShutdownHook() {
		if (this.shutdownHook == null) {
			// No shutdown hook registered yet.
			this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
				@Override
				public void run() {
					synchronized (startupShutdownMonitor) {
						doClose();
					}
				}
			};
			Runtime.getRuntime().addShutdownHook(this.shutdownHook);
		}
	}
	
	
	protected void doClose() {
		// Check whether an actual close attempt is necessary...
		if (this.active.get() && this.closed.compareAndSet(false, true)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Closing " + this);
			}

			LiveBeansView.unregisterApplicationContext(this);

			try {
				// Publish shutdown event.
				publishEvent(new ContextClosedEvent(this));
			}
			catch (Throwable ex) {
				logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
			}

			// Stop all Lifecycle beans, to avoid delays during individual destruction.
			if (this.lifecycleProcessor != null) {
				try {
					this.lifecycleProcessor.onClose();
				}
				catch (Throwable ex) {
					logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
				}
			}

			// Destroy all cached singletons in the context's BeanFactory.
			destroyBeans();

			// Close the state of this context itself.
			closeBeanFactory();

			// Let subclasses do some final clean-up if they wish...
			onClose();

			// Reset local application listeners to pre-refresh state.
			if (this.earlyApplicationListeners != null) {
				this.applicationListeners.clear();
				this.applicationListeners.addAll(this.earlyApplicationListeners);
			}

			// Switch to inactive.
			this.active.set(false);
		}
	}

模板方法afterRefresh

不做任何實現

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

關閉監視器,打印啓動耗時

2020-04-16 19:34:40.634  INFO 9204 --- [           main] c.e.factory.app.FactoryDemoApplication   : Started FactoryDemoApplication in 211.377 seconds (JVM running for 212.963)

推送應用啓動事件ApplicationStartedEvent

0 = {BackgroundPreinitializer@29405} 
1 = {DelegatingApplicationListener@29406} 

回調實現了ApplicationRunner和CommandLineRunner接口的實例

private void callRunners(ApplicationContext context, ApplicationArguments args) {
		List<Object> 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);
			}
		}
	}

推送運行中事件ApplicationReadyEvent

0 = {SpringApplicationAdminMXBeanRegistrar@6596} 
1 = {BackgroundPreinitializer@6920} 
2 = {DelegatingApplicationListener@6921} 

啓動完畢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章