Spring之SpringBoot启动过程

前言

SpringBoot的启动过程比较长,会涉及到其他模块的事件/监听器,这些监听器里又会有自己的逻辑;本文重点集中在启动过程上,对于比较重要的,对全局有影响的监听器也会单独拎出,说明它的作用。文章很长,先给出启动的大致流程:
在这里插入图片描述

启动类

@SpringBootApplication
public class WebApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebApplication.class, args);
    }

}

SpringApplication#run(java.lang.Class<?>, java.lang.String...)这个方法有两步:

  1. 创建SpringApplication
  2. 调用run方法;

new SpringApplication()

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();
		// 从spring.factories里搜索`ApplicationContextInitializer`类
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		// 从spring.factories里搜索`ApplicationListener`类
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

run方法

run方法就比较重要了。这里先概览下,下面再分步慢慢分析。

public ConfigurableApplicationContext run(String... args) {
    // 计数秒表
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
	configureHeadlessProperty();
	// 从spring.factories里搜索`SpringApplicationRunListener`类
	// 会找到`EventPublishingRunListener`
	SpringApplicationRunListeners listeners = getRunListeners(args);
	// 调用`SpringApplicationRunListener`里的`starting`方法
	// 在`EventPublishingRunListener`里会构建一个`ApplicationStartingEvent`事件
	// 并找出监听该事件的监听器然后调用
	listeners.starting();
	try {
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		// 准备环境
		// 会将启动命令里的变量以及系统的环境变量放到两个PropertiesPropertySource里
		// 将该环境对象绑定到当前的`SpringApplication`上
		ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
		// 取环境变量里的`spring.beaninfo.ignore`,并将其设置到系统对象里去
		configureIgnoreBeanInfo(environment);
		// 打印banner,可通过`spring.banner.location`属性执行自己的banner
		Banner printedBanner = printBanner(environment);
		// 创建`ConfigurableApplicationContext`
		context = createApplicationContext();
		// 从spring.factories里搜索`SpringBootExceptionReporter`类
		exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
				new Class[] { ConfigurableApplicationContext.class }, context);
		prepareContext(context, environment, listeners, applicationArguments, printedBanner);
		refreshContext(context);
		// 在`SpringApplication`中,该方法为空方法
		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, exceptionReporters, listeners);
		throw new IllegalStateException(ex);
	}

	try {
	    // 调用`SpringApplicationRunListener`里的`running`方法
	    // 在`EventPublishingRunListener`里会构建一个`ApplicationReadyEvent`事件
	    // 并找出监听该事件的监听器然后调用
		listeners.running(context);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, exceptionReporters, null);
		throw new IllegalStateException(ex);
	}
	return context;
}

下面会以listeners.startingprepareEnvironmentcreateApplicationContextprepareContextrefreshContext为入口依次分析。

EventPublishingRunListener

run的方法里注释里我们提到目前的SpringApplicationRunListener只找到一个EventPublishingRunListener:

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
    @Override
	public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}

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

	@Override
	public void contextPrepared(ConfigurableApplicationContext context) {
		this.initialMulticaster
				.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
	}
	
		@Override
	public void multicastEvent(ApplicationEvent event) {
		multicastEvent(event, resolveDefaultEventType(event));
	}

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

从上面的代码可以看出,EventPublishingRunListener是作为一个广播器的存在,构造事件并将事件广播给符合条件的监听器。

listeners.starting

listeners.starting是发出了一个ApplicationStartingEvent事件,通过断点我们可以看到有以下几个监听器监听了改事件:

  • LoggingApplicationListener: 获取日志系统,选项有:ch.qos.logback.core.Appenderorg.apache.logging.log4j.core.impl.Log4jContextFactoryjava.util.logging.LogManager; 并执行beforeInitialize将日志系统重置为限制输出
  • BackgroundPreinitializer: 对于一些耗时的任务使用一个后台线程尽早触发它们开始执行初始化

prepareEnvironment

先看下它的方法体:

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
		ApplicationArguments applicationArguments) {
	// 创建环境对象
	ConfigurableEnvironment environment = getOrCreateEnvironment();
	// 根据启动参数配置环境
	configureEnvironment(environment, applicationArguments.getSourceArgs());
	// 给`environment`附件一个`ConfigurationPropertySource`
	ConfigurationPropertySources.attach(environment);
	// 调用`SpringApplicationRunListener`里的`environmentPrepared`方法
    // 在`EventPublishingRunListener`里会构建一个`ApplicationEnvironmentPreparedEvent`事件
    // 并找出监听该事件的监听器然后调用
	listeners.environmentPrepared(environment);
	// 将`environment`对象绑定到当前的`SpringApplication`
	bindToSpringApplication(environment);
	if (!this.isCustomEnvironment) {
	    // 将`environment`转换成`StandardServletEnvironment`类型
		environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
				deduceEnvironmentClass());
	}
	// 重新给`environment`附件一个`ConfigurationPropertySource`
	ConfigurationPropertySources.attach(environment);
	return environment;
}

下面我们要一个个方法进去进行细致的分析。

getOrCreateEnvironment

private ConfigurableEnvironment getOrCreateEnvironment() {
	if (this.environment != null) {
		return this.environment;
	}
	// 我们这里的webApplicationType是SERVLET
	switch (this.webApplicationType) {
	case SERVLET:
		return new StandardServletEnvironment();
	case REACTIVE:
		return new StandardReactiveWebEnvironment();
	default:
		return new StandardEnvironment();
	}
}

继续探索new StandardServletEnvironment()时做了什么工作:

public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {
	@Override
	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);
	}

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

发现没有构造函数,我们继续找他的父类:

public class StandardEnvironment extends AbstractEnvironment {
	@Override
	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()));
	}
}

依旧没有,继续向上:

public abstract class AbstractEnvironment implements ConfigurableEnvironment {

	private final MutablePropertySources propertySources = new MutablePropertySources();

	private final ConfigurablePropertyResolver propertyResolver =
			new PropertySourcesPropertyResolver(this.propertySources);

	public AbstractEnvironment() {
		customizePropertySources(this.propertySources);
	}
}

找到了,在构造函数里调用了customizePropertySources方法。我们再往回看知道它加了两个StubPropertySource,又调用了父类customizePropertySources加了一个PropertiesPropertySourceSystemEnvironmentPropertySource,这两个PropertySource分别保存启动命令里的变量以及系统环境变量

configureEnvironment

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    // 在`SpringApplication`中为true
    // 设置了一个`ApplicationConversionService`,满足大多数`springboot`应用的类型转换与格式化需求
    // 
	if (this.addConversionService) {
		ConversionService conversionService = ApplicationConversionService.getSharedInstance();
		environment.setConversionService((ConfigurableConversionService) conversionService);
	}
	// 添加来自命令行的属性
	configurePropertySources(environment, args);
	// 添加额外的配置文件到环境对象去
	// 已有的配置文件从`spring.profiles.active`属性里获取
	// 额外的配置文件是当前`SpringApplication`里的`additionalProfiles`值
	configureProfiles(environment, args);
}

现在我们看下ApplicationConversionService给我们预置了哪些converterformatter:

registry.addConverter(new StringToDurationConverter());
registry.addConverter(new DurationToStringConverter());
registry.addConverter(new NumberToDurationConverter());
registry.addConverter(new DurationToNumberConverter());
registry.addConverter(new StringToPeriodConverter());
registry.addConverter(new PeriodToStringConverter());
registry.addConverter(new NumberToPeriodConverter());
registry.addConverter(new StringToDataSizeConverter());
registry.addConverter(new NumberToDataSizeConverter());
registry.addConverter(new StringToFileConverter());
registry.addConverter(new InputStreamSourceToByteArrayConverter());
registry.addConverterFactory(new LenientStringToEnumConverterFactory());
registry.addConverterFactory(new LenientBooleanToEnumConverterFactory());

ConfigurationPropertySources.attach

public static void attach(Environment environment) {
	Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
	MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
	// 获取环境对象里名为`ATTACHED_PROPERTY_SOURCE_NAME`的`PropertySource`
	// 从`getOrCreateEnvironment`方法的分析我们可以看到,当时并没有添加这个`PropertySource`
	PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
	if (attached != null && attached.getSource() != sources) {
		sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
		attached = null;
	}
	// 给环境对象添加`ConfigurationPropertySourcesPropertySource`
	// 将当前已有的`PropertySource`设置到`ConfigurationPropertySourcesPropertySource`里去
	// 目前还不知道为什么要这样设计
	if (attached == null) {
		sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
				new SpringConfigurationPropertySources(sources)));
	}
}

listeners.environmentPrepared

通过断点,发现目前的SpringApplicationRunListener只有一个EventPublishingRunListener,所以我们直接看EventPublishingRunListener里的environmentPrepared方法。

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

创建了一个ApplicationEnvironmentPreparedEvent,然后多播:

@Override
public void multicastEvent(ApplicationEvent event) {
	multicastEvent(event, resolveDefaultEventType(event));
}

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

通过断点,我们知道有以下几个org.springframework.boot内置的监听器监听了ApplicationEnvironmentPreparedEvent事件:

  • ConfigFileApplicationListener:委派给EnvironmentPostProcessor,通过从众所周知的文件位置加载属性来配置上下文环境:
    1. SystemEnvironmentPropertySourceEnvironmentPostProcessorenvironment里的SystemEnvironmentPropertySource替换为OriginAwareSystemEnvironmentPropertySource[ps: 不知道为什么要替换]
    2. SpringApplicationJsonEnvironmentPostProcessorspring.application.json/SPRING_APPLICATION_JSON的值以JSON的方式解析,并将key-value放入配置中。
    3. ConfigFileApplicationListener,通过PropertiesPropertySourceLoader/YamlPropertySourceLoader加载配置文件中的配置项,使用PropertySourcesPlaceholdersResolver处理占位符。
  • AnsiOutputApplicationListener: 在控制台打印彩色日志
  • LoggingApplicationListener: 初始化日志系统,
    1. 设置logfile以及各个package的日志level
    2. 根据logging.register-shutdown-hook配置判断是否需要注册Shutdown事件的钩子。
  • ClasspathLoggingApplicationListener: 以debug级别记录线程上下文类加载器 (TCCL) 的类路径
  • DelegatingApplicationListener: 将事件委派context.listener.classes指定的事件监听器
  • FileEncodingApplicationListener: 当文件系统的编码与预期不符时,会终止应用的启动。预期编码通过spring.mandatory-file-encoding指定/获取,文件系统编码通过file.encoding指定/获取。

bindToSpringApplication

protected void bindToSpringApplication(ConfigurableEnvironment environment) {
	try {
	    // 将`environment`对象绑定到当前的`SpringApplication`对象上
		Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
	}
	catch (Exception ex) {
		throw new IllegalStateException("Cannot bind to SpringApplication", ex);
	}
}

ConfigurationPropertySources.attach

prepareEnvironment最后又执行了一次ConfigurationPropertySources.attach;根据代码可以看出,这次执行会将上一步添加ATTACHED_PROPERTY_SOURCE_NAMEenvironment对象里移除。

小结

这节我们梳理了启动过程中的准备环境这一步,下面给出流程图:
在这里插入图片描述

createApplicationContext

protected ConfigurableApplicationContext createApplicationContext() {
	Class<?> contextClass = this.applicationContextClass;
	if (contextClass == null) {
		try {
			switch (this.webApplicationType) {
			case SERVLET:
			    // org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
				contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
				break;
			case REACTIVE:
			    // org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext
				contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
				break;
			default:
				contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
			}
		}
		catch (ClassNotFoundException ex) {
			throw new IllegalStateException(
					"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
		}
	}
	return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

我们使用SERVLET

public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext{
    // 创建了`AnnotatedBeanDefinitionReader`以及`ClassPathBeanDefinitionScanner`
	public AnnotationConfigServletWebServerApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
}
// AnnotationConfigServletWebServerApplicationContext
<- ServletWebServerApplicationContext
<- GenericWebApplicationContext
<- GenericApplicationContext
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}
}

createApplicationContext方法是非常简单的,单独拎出来是想看看他的构造函数里做了什么。

prepareContext准备上下文

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
		SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
	// 将准备好的环境对象设置到context里
	context.setEnvironment(environment);
	// 设置context里的`resourceLoader`/`classLoader`
	// 设置context.beanFactory里的`beanNameGenerator`以及`conversionService`
	postProcessApplicationContext(context);
	// 依次调用`ApplicationContextInitializer`的`initialize`方法
	applyInitializers(context);
	// 向事件监听器发布`ApplicationContextInitializedEvent`事件
	// 目前系统中并没有这样的监听器
	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);
	}
	// 如果符合懒加载,添加一个`LazyInitializationBeanFactoryPostProcessor`
	if (this.lazyInitialization) {
		context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
	}
	// Load the sources
	Set<Object> sources = getAllSources();
	Assert.notEmpty(sources, "Sources must not be empty");
	// 将Bean Definition加载到context去
	load(context, sources.toArray(new Object[0]));
	// 向事件监听器发布`ApplicationPreparedEvent`事件
	listeners.contextLoaded(context);
}

context.setEnvironment() & postProcessApplicationContext

context.setEnvironment() & postProcessApplicationContext这两个方法比较直观,没有那么多弯弯绕绕。

// context.setEnvironment
public void setEnvironment(ConfigurableEnvironment environment) {
	super.setEnvironment(environment);
	// 创建一个ConditionEvaluator
	// ConditionEvaluator评估有@ConditionOnXXX注解的组件类是否需要注册
	this.reader.setEnvironment(environment);
	this.scanner.setEnvironment(environment);
}

// postProcessApplicationContext
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
    // 目前的`beanNameGenerator`与`resourceLoader`都为null
	if (this.beanNameGenerator != null) {
		context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
				this.beanNameGenerator);
	}
	if (this.resourceLoader != null) {
		if (context instanceof GenericApplicationContext) {
			((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
		}
		if (context instanceof DefaultResourceLoader) {
			((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());
		}
	}
	// ApplicationConversionService在`prepareEnvironment`阶段已生成
	// 这里拿到当时创建的单例设置到beanFactory里去
	if (this.addConversionService) {
		context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());
	}
}

applyInitializers

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

initializers在SpringApplication构造函数里已获得:

  • DelegatingApplicationContextInitializer: 委派给context.listener.classes指定的初始化器进行处理
  • ContextIdApplicationContextInitializer: 以spring.application.name为ID, 创建一个ContextId,并以单例的方式注册到context
  • ConditionEvaluationReportLoggingListener: 向context添加ConditionEvaluationReportListener监听器,在接受到事件ContextRefreshedEventApplicationFailedEvent时,以debug的等级记录条件评估(ConditionEvaluation)的详细信息
  • ConfigurationWarningsApplicationContextInitializer: 报告常见错误配置的警告
  • ServerPortInfoApplicationContextInitializer: 向context添加一个监听WebServerInitializedEvent事件的监听器(ps: 其实就是它自己)

load

将 bean 加载到应用程序上下文中。

// 这里的sources是我们的启动类
protected void load(ApplicationContext context, Object[] sources) {
	BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
	// `beanNameGenerator`/`resourceLoader`/`environment`为null
	...
	loader.load();
}

protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) {
	return new BeanDefinitionLoader(registry, sources);
}

BeanDefinitionLoader

class BeanDefinitionLoader {
    // 需要注意使用的reader/scanner类
	BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
		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));
	}

    int load() {
    	int count = 0;
    	for (Object source : this.sources) {
    		count += load(source);
    	}
    	return count;
    }
    
    private int load(Object source) {
    	Assert.notNull(source, "Source must not be null");
    	if (source instanceof Class<?>) {
    		return load((Class<?>) source);
    	}
    	...
    }
    
    private int load(Class<?> source) {
        // Groovy
    	if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
    		...
    	}
    	// 非匿名类、非Groove闭包、有无参构造函数
    	if (isEligible(source)) {
    	    // 在`AnnotatedBeanDefinitionReader`一节中,我们知道`annotatedReader`的类是`AnnotatedBeanDefinitionReader`
    		this.annotatedReader.register(source);
    		return 1;
    	}
    	return 0;
    }
    
    private boolean isEligible(Class<?> type) {
    	return !(type.isAnonymousClass() || isGroovyClosure(type) || hasNoConstructors(type));
    }
    ...
}

AnnotatedBeanDefinitionReader

public class AnnotatedBeanDefinitionReader {
    // 这里的componentClasses只有一个当前项目的启动类
	public void register(Class<?>... componentClasses) {
		for (Class<?> componentClass : componentClasses) {
			registerBean(componentClass);
		}
	}
	
	public void registerBean(Class<?> beanClass) {
		doRegisterBean(beanClass, null, null, null, null);
	}
	
	private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {

		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		// 通过`@ConditionXXX`注解判断是否要加载
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(supplier);
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
        // 根据类上的`Lazy`/`Primary`/`DependsOn`/`Role`/`Description`注解,设置相应的abd属性
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		if (qualifiers != null) {
			...
		}
		if (customizers != null) {
			...
		}
        // 将启动类的BeanDefinition封装成BeanDefinitionHolder,并将其注册到`registry`[其实就是context]
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}
}

listeners.contextLoaded

上文已述在当前的SpringApplicationlisteners里只有一个元素-EventPublishingRunListener,这个类里的contextLoaded方法将SpringApplication对象里的ApplicationListener数组先同步到context里,再广播ApplicationPreparedEvent事件:

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

通过断点,我们知道有以下几个org.springframework.boot内置的监听器监听了ApplicationPreparedEvent事件:

  • ConfigFileApplicationListener:添加PropertySourceOrderingPostProcessor; 将Environment对象中的缺省属性源(名为"defaultProperties")放到最低优先级
  • LoggingApplicationListener: 将准备好的日志相关的对象注册为单例
  • DelegatingApplicationListener: 将事件委派context.listener.classes指定的事件监听器

小结

这节我们梳理了启动过程中的准备上下文这一步,下面给出流程图:
在这里插入图片描述

refreshContext刷新应用上下文

refreshContext进行调用链追踪,它的真实面目就是org.springframework.context.support.AbstractApplicationContext#refresh

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 准备刷新
		// 会进行一些数据清理以及校验
		prepareRefresh();

		// 获取beanFactory对象
		// 在当前的context中是设置beanFactory的serializationId,并返回
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 准备在此上下文中使用的bean工厂。
		prepareBeanFactory(beanFactory);

		try {
			// 在子类里对beanFactory进行后置处理
			postProcessBeanFactory(beanFactory);

			// 执行已注册为bean的beanFactory后置处理器
			invokeBeanFactoryPostProcessors(beanFactory);

			// 实例化和注册所有BeanPostProcessor bean
			registerBeanPostProcessors(beanFactory);

			// 初始化MessageSource
			// MessageSource是用于解析消息的策略接口,支持此类消息的参数化和国际化。
			initMessageSource();

			// 初始化ApplicationEventMulticaster。
			//如果上下文中没有定义,则使用SimpleApplicationEventMulticaster。
			initApplicationEventMulticaster();

			// 初始化特定的bean
			onRefresh();

			// 添加实现ApplicationListener的bean
			registerListeners();

			// 实例化所有剩余的(non-lazy-init)单例对象
			finishBeanFactoryInitialization(beanFactory);

			// 完成此上下文的刷新
			// 调用 LifecycleProcessor 的 onRefresh() 方法并发布 ContextRefreshedEvent事件
			finishRefresh();
		}

		catch (BeansException ex) {
			...
		}

		finally {
			// 重置Spring的公共反射元数据缓存,特别是ReflectionUtils, AnnotationUtils, ResolvableType和CachedIntrospectionResults缓存。 
			resetCommonCaches();
		}
	}
}

下面会从prepareRefreshprepareBeanFactorypostProcessBeanFactoryinvokeBeanFactoryPostProcessorsregisterBeanPostProcessorsinitMessageSourceinitApplicationEventMulticasteronRefreshregisterListenersfinishBeanFactoryInitializationfinishRefresh依次进行分析,比较简单的方法会放在一起。

prepareRefresh刷新前准备

protected void prepareRefresh() {
	this.startupDate = System.currentTimeMillis();
	this.closed.set(false);
	this.active.set(true);
    ...
	// 初始化上下文环境中的任何占位符属性源
	// 还记得在`准备环境`一节中,创建Environment[StandardServletEnvironment]对象时添加的两个`StubPropertySource`吗
	// 这一步就是想要替换这两个PropertySource
	// 但是由于当前context的`servletContext`与`servletConfig`都为null,所以并没有替换
	initPropertySources();

	// 验证所有标记为required的属性都是可解析的 
	// 目前没有属性被标记为required
	getEnvironment().validateRequiredProperties();

	// 将`applicationListeners`元素复制到`earlyApplicationListeners`
	if (this.earlyApplicationListeners == null) {
		this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
	}
	else {
		this.applicationListeners.clear();
		this.applicationListeners.addAll(this.earlyApplicationListeners);
	}
    // 初始化`earlyApplicationEvents`属性
	this.earlyApplicationEvents = new LinkedHashSet<>();
}

obtainFreshBeanFactory & prepareBeanFactory

这两个方法比较简单:

  • obtainFreshBeanFactory就是指定context里beanFactory里的serializationId,并将其返回;
  • prepareBeanFactory:配置beanFactory的属性,如:beanClassLoaderbeanPostProcessorbeanExpressionResolver等以及设置不自动装配的接口和使用指定的值去自动装配指定的类型:
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    	// Tell the internal bean factory to use the context's class loader etc.
    	beanFactory.setBeanClassLoader(getClassLoader());
    	beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    	beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    
    	// Configure the bean factory with context callbacks.
    	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);
    
    	// BeanFactory interface not registered as resolvable type in a plain factory.
    	// MessageSource registered (and found for autowiring) as a bean.
    	beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    	beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    	beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    	beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    
    	// Register early post-processor for detecting inner beans as ApplicationListeners.
    	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    
    	...
    }
    

postProcessBeanFactory

在应用程序上下文的标准初始化之后修改其内部beanFactory:

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 执行父类的`postProcessBeanFactory`
    // 这里的父类是`ServletWebServerApplicationContext`
	super.postProcessBeanFactory(beanFactory);
	// 我们的启动类里未指定`basePackages`
	// 这里不执行`scan`
	if (this.basePackages != null && this.basePackages.length > 0) {
		this.scanner.scan(this.basePackages);
	}
	// `annotatedClasses`为空,这里不执行`register`
	if (!this.annotatedClasses.isEmpty()) {
		this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
	}
}

ServletWebServerApplicationContext#postProcessBeanFactory

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 添加一个`BeanPostProcessor`
	beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
	// 设置`ServletContextAware`的依赖不自动装配
	beanFactory.ignoreDependencyInterface(ServletContextAware.class);
	// 注册Web应用的作用域
	// web应用的作用域有:`request`/`session`/`application`
	registerWebApplicationScopes();
}

invokeBeanFactoryPostProcessors执行后置处理器

实例化和调用所有已注册的BeanFactoryPostProcessor:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 这里会执行两种后置处理
    // 1. postProcessBeanDefinitionRegistry
    // 2. postProcessBeanFactory
    // `getBeanFactoryPostProcessors`会得到3个`BeanFactoryPostProcessor`
    // - SharedMetadataReaderFactoryContextInitializer.CachingMetadataReaderFactoryPostProcessor
    // - ConfigurationWarningsApplicationContextInitializer.ConfigurationWarningsPostProcessor
    // - ConfigFileApplicationListener.PropertySourceOrderingPostProcessor
	PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

	// 设置`beanFactory`属性
	if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}
}

下面我们详细看下PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法,这个方法很长:

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

	Set<String> processedBeans = new HashSet<>();
    // 这里用的`beanFactory`是`DefaultListableBeanFactory`属于`BeanDefinitionRegistry`
	if (beanFactory instanceof BeanDefinitionRegistry) {
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        // 在上文提到的三个postProcessor中,`CachingMetadataReaderFactoryPostProcessor`与`ConfigurationWarningsPostProcessor`都属于`BeanDefinitionRegistryPostProcessor`
		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
				BeanDefinitionRegistryPostProcessor registryProcessor =
						(BeanDefinitionRegistryPostProcessor) postProcessor;
				// ConfigurationWarningsPostProcessor在该方法里检查了@ComponentScan里设置的包[不能在'org'/'org.springframework'中]
				// CachingMetadataReaderFactoryPostProcessor添加了一个名为`org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory`的`SharedMetadataReaderFactoryBean`
				// 以及设置`org.springframework.context.annotation.internalConfigurationAnnotationProcessor`的`metadataReaderFactory`属性[为一个`RuntimeBeanReference`]
				registryProcessor.postProcessBeanDefinitionRegistry(registry);
				registryProcessors.add(registryProcessor);
			}
			else {
				regularPostProcessors.add(postProcessor);
			}
		}
		
		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

		// 调用实现了`PriorityOrdered`的`BeanDefinitionRegistryPostProcessor`的`postProcessBeanDefinitionRegistry`方法
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		registryProcessors.addAll(currentRegistryProcessors);
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		// 调用实现了`Ordered`的`BeanDefinitionRegistryPostProcessor`的`postProcessBeanDefinitionRegistry`方法[与上面重复的不加入currentRegistryProcessors]
		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		registryProcessors.addAll(currentRegistryProcessors);
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		//执行其他未执行过的`BeanDefinitionRegistryPostProcessor`
		// 为什么`postProcessorNames`要多次获取呢?
		// `getBeanNamesForType`设置了缓存,且在执行各个`beanDefinitionRegistryPostProcessors`方法时,有可能会添加BeanDefinition
		BeanDefinitionRegistryPostProcessors until no further ones appear.
		boolean reiterate = true;
		while (reiterate) {
			reiterate = false;
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
					reiterate = true;
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();
		}

		// 执行各个后置处理器的`beanFactoryPostProcessors`方法
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	}

	else {
		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
	}

	// 有漏掉的`BeanFactoryPostProcessor`,根据是否有实现PriorityOrdered/Ordered接口进行顺序调用`postProcessBeanFactory`方法
	// 会根据`processedBeans`跳过已执行过的后置处理器
	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) {
		if (processedBeans.contains(ppName)) {
			// skip - already processed in first phase above
		}
		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);
		}
	}
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

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

BeanDefinitionRegistryPostProcessor

下面罗列用到的BeanDefinitionRegistryPostProcessor以及说明它们的具体作用:

只考虑springboot自带的, 暂不考虑其他组件引入的BeanDefinitionRegistryPostProcessor

  • ConfigurationClassPostProcessor: 该后置处理器会先载入当前beanFactory中有@Configuration注解的类;然后遍历找到的类,按序解析其上的@Component/@PropertySource/@ComponentScan注解,并递归解析@ComponentScan扫描到的@Component;再然后载入libraries里jar包下spring.factories中的EnableAutoConfiguration;最后解析类里的带@Bean的方法,类上的@ImportResource注解引入的xml文件以及@Import导入的ImportBeanDefinitionRegistrar。我们的启动类就是其中的一个@Configuration类,启动类上的@SpringBootApplication注解是个复合注解,里面就有@ComponentScan,所以在这一步,我们将应用层的各种beanDefinition载入到beanFactory

BeanFactoryPostProcessor

下面罗列用到的BeanFactoryPostProcessor以及说明它们的具体作用:

只考虑springboot自带的, 暂不考虑其他组件引入的BeanFactoryPostProcessor

  • ConfigurationClassPostProcessor: 使用ConfigurationClassEnhancer增强Configuration类来支持@Bean定义的bean scope,并添加一个ImportAwareBeanPostProcessor后置处理器;
  • ConfigFileApplicationListener: 将默认的配置文件放到PropertySource列表的最后面;
  • PropertySourcesPlaceholderConfigurer: 通过创建一个StringValueResolver对象,处理容器里bean别名中的${...}占位符,再将StringValueResolver对象添加到beanFactoryembeddedValueResolvers列表里,后续处理@Value、配置、注解中的${...}占位符;
  • EventListenerMethodProcessor: 这个类的作用是将@EventListener方法封装成一个个独立的ApplicationListener实例;在postProcessBeanFactory方法中先实例化EventListenerFactory的bean;
  • PreserveErrorControllerTargetClassPostProcessor: 通过给ErrorControllerbeanDefinition设置preserveTargetClasstrue来确保在使用AOP时保留它的目标类

registerBeanPostProcessors

实例化容器里的BeanPostProcessor类,并按序加入到beanFactorybeanPostProcessors。下面我们看下系统预置的这些BeanPostProcessor会有什么作用:

  • ApplicationContextAwareProcessor: 如果一个bean有实现部分Aware接口,在bean初始化调用其相应的设置方法;
  • WebApplicationContextServletContextAwareProcessor: 将servletContext/servletConfig分别传递给ServletContextAware/ServletConfigAware对象;
  • ImportAwareBeanPostProcessor: 设置ImportAwareimportMetadata
  • BeanPostProcessorChecker: 当一个bean是在BeanPostProcessor实例化期间创建的,通过这个处理器记录;
  • ConfigurationPropertiesBindingPostProcessor: 解析bean上的注解@ConfigurationProperties,将属性源中的属性设置到bean。
  • AnnotationAwareAspectJAutoProxyCreator: AOP入口,详情可查看之前的文章:Spring之AOP源码
  • DataSourceInitializerPostProcessor: 强制初始化DataSourceInitializerDataSource初始化时。
  • AsyncAnnotationBeanPostProcessor: 向有@Async注解的类或方法添加AsyncAnnotationAdvisor增强,用于异步执行;
  • RabbitListenerAnnotationBeanPostProcessor: 通过解析bean或bean方法上的@RabbitListener/@RabbitHandler注解,添加RabbitListenerEndpoint实例;
  • MethodValidationPostProcessor: 对符合条件的bean添加一个MethodValidationInterceptor增强,达到对有@Validated的类、方法、属性进行校验;
  • PersistenceExceptionTranslationPostProcessor: 对符合条件的bean添加一个PersistenceExceptionTranslationAdvisor,用于转换持久化异常信息;
  • WebServerFactoryCustomizerBeanPostProcessor: 将载入的WebServerFactorybean应用到WebServerFactoryCustomizer去;
  • ErrorPageRegistrarBeanPostProcessor: 将载入的ErrorPageRegistrybean应用到ErrorPageRegistry去;
  • ProjectingArgumentResolverBeanPostProcessor: 将ProxyingHandlerMethodArgumentResolver加入到载入的RequestMappingHandlerAdapterbean的ArgumentResolvers列表第一个;
  • ConfigurationPropertiesBeans: 收集有@ConfigurationProperties的bean;
  • ApplicationListenerDetector: ApplicationListener探测器,如果载入的bean是ApplicationListener就将其加入在context的applicationListeners列表里;

initMessageSource & initApplicationEventMulticaster

  1. initMessageSource:初始化MessageSource,用于处理国际化场景;
  2. initApplicationEventMulticaster:创建一个SimpleApplicationEventMulticaster并添加到beanFactory;

onRefresh

protected void onRefresh() {
    // 初始化主题功能
    // 这里不再深入了
	super.onRefresh();
	try {
	    // 创建web服务
		createWebServer();
	}
	catch (Throwable ex) {
		throw new ApplicationContextException("Unable to start web server", ex);
	}
}

createWebServer

private void createWebServer() {
	WebServer webServer = this.webServer;
	ServletContext servletContext = getServletContext();
	// 一开始webServer为null
	if (webServer == null && servletContext == null) {
	    // 本文使用的是`TomcatServletWebServerFactory`
		ServletWebServerFactory factory = getWebServerFactory();
		// 创建WebServer
		// 其实在这一步tomcat服务器已经启动了,但是我们的应用还未完全准备好,尚不能对外提供服务
		// 这里的过程比较长,会单开一篇文章分析
		this.webServer = factory.getWebServer(getSelfInitializer());
		// 往beanFactory里注册两个单例:webServerGracefulShutdown、webServerStartStop
		// 这两个都是实现了`SmartLifecycle`接口
		// WebServer将在`WebServerStartStopLifecycle`的start回调里启动
		getBeanFactory().registerSingleton("webServerGracefulShutdown",
				new WebServerGracefulShutdownLifecycle(this.webServer));
		getBeanFactory().registerSingleton("webServerStartStop",
				new WebServerStartStopLifecycle(this, this.webServer));
	}
	else if (servletContext != null) {
		try {
			getSelfInitializer().onStartup(servletContext);
		}
		catch (ServletException ex) {
			throw new ApplicationContextException("Cannot initialize servlet context", ex);
		}
	}
	// 这个方法之前也出现过,只不过当时的`servletContext`与`servletConfig`都为null
	// 在这里通过`getWebServer`方法,`servletContext`被设置为`ApplicationContextFacade`
	// 替换之前的占位`PropertySource`: servletContextInitParams
	initPropertySources();
}

registerListeners 注册ApplicationListener

添加实现ApplicationListener作为侦听器的bean:

protected void registerListeners() {
	// 将之前载入的`ApplicationListener`[来源有从`spring.factories`中读取,也有在事件监听器里添加的]
	// 添加到`ApplicationEventMulticaster`去
	// `ApplicationEventMulticaster`是在`initApplicationEventMulticaster`这边创建的`SimpleApplicationEventMulticaster`
	for (ApplicationListener<?> listener : getApplicationListeners()) {
		getApplicationEventMulticaster().addApplicationListener(listener);
	}

	// 从容器的BeanDefinition里找出实现`ApplicationListener`接口的beanName
	// 注意,这里还只是beanName,并不是bean
	// 后面有需要的时候,再实例化真正的bean
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) {
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
	}

	// 如果有早期的事件,在这里先广播
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
		}
	}
}

finishBeanFactoryInitialization完成非lazy-init bean的初始化

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// 将beanName为`conversionService`的bean,设置到beanFactory的`conversionService`属性
	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));
	}

	// 在`invokeBeanFactoryPostProcessors`方法的解析里
	// 我们有提到`PropertySourcesPlaceholderConfigurer`这个`BeanFactoryPostProcessor`
	// 会添加一个`StringValueResolver`到beanFactory的`embeddedValueResolver`列表里
	// 所以这里就不必再生成一个`StringValueResolver`了
	if (!beanFactory.hasEmbeddedValueResolver()) {
		beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
	}

	// 预先加载`LoadTimeWeaverAware`
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
	for (String weaverAwareName : weaverAwareNames) {
		getBean(weaverAwareName);
	}

	beanFactory.setTempClassLoader(null);

	// 冻结所有的bean definition,不期望做进一步的改变
	// 这里的冻结就是将beanFactory的`configurationFrozen`置为true
	// 然后将所有beanDefinitionNames复制到beanFactory的`frozenBeanDefinitionNames`属性去
	beanFactory.freezeConfiguration();

	// 实例化剩余未实例化的非懒加载的单例bean
	// 实例化完成后,再对实现`SmartInitializingSingleton`接口的bean,回调它的`afterSingletonsInstantiated`方法
	// 如何实例化,这里先不展开了
	beanFactory.preInstantiateSingletons();
}

finishRefresh

完成上下文的刷新,调用LifecycleProcessoronRefresh()方法并发布contextrefreshdevent事件。

protected void finishRefresh() {
	// 清理资源缓存
	clearResourceCaches();

	// 初始化`LifecycleProcessor`
	// 即:若当前beanFactory里存在`LifecycleProcessor`的实例或者bean definition就进行实例化;
	// 若不存在就创建一个`DefaultLifecycleProcessor`对象
	// 将最终获取的对象放入beanFactory的`lifecycleProcessor`属性里
	initLifecycleProcessor();

	// 调用`LifecycleProcessor`的onRefresh方法
	// 在`DefaultLifecycleProcessor`中,该方法从容器里获取`Lifecycle`类型的bean
	// 并依次调用他们的`start`方法
	// 其中就有webServer的start
	getLifecycleProcessor().onRefresh();

	// 发布`ContextRefreshedEvent`事件
	// 与web服务相关的一个监听器是`ResourceUrlProvider`,这个监听器`ContextRefreshedEvent`事件里初始化静态资源的访问路径
	publishEvent(new ContextRefreshedEvent(this));

	// 将当前上下文放入`MBean`(MBean如果可用的话)
	LiveBeansView.registerApplicationContext(this);
}

小结

refreshContext可以说是启动过程的重点了,涉及了web服务启动,IOC等;前面写的过程也很长,下面通过一个流程图,来回忆与总结下:

在这里插入图片描述

收尾

接下来的操作比较直观了:

  1. 调用SpringApplicationRunListener``started方法,当前context对象里这种类型的监听器只有EventPublishingRunListenerEventPublishingRunListener会构造一个ApplicationStartedEvent事件并广播出去;发布应用状态变更事件LivenessState.CORRECT
  2. 获取容器中的ApplicationRunner以及CommandLineRunner,并依次调用;
  3. 调用SpringApplicationRunListener``running方法,当前context对象里这种类型的监听器只有EventPublishingRunListenerEventPublishingRunListener会构造一个ApplicationReadyEvent事件并广播出去;发布应用状态变更事件ReadinessState.ACCEPTING_TRAFFIC
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值