SpringBoot 启动类 SpringApplication 三 配置IOC容器

发布于:2025-02-11 ⋅ 阅读:(39) ⋅ 点赞:(0)

配置IOC容器

public ConfigurableApplicationContext run(String... args) {
	// -- snip
		try {
			// context的类型是AnnotationConfigServletWebServerApplicationContext
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
			// 1. 准备容器
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			// 2. 刷新容器
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			startup.started();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), startup);
			}
			listeners.started(context, startup.timeTakenToStarted());
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			throw handleRunFailure(context, ex, listeners);
		}
		try {
			if (context.isRunning()) {
				listeners.ready(context, startup.ready());
			}
		}
		catch (Throwable ex) {
			throw handleRunFailure(context, ex, null);
		}
		return context;
	}

1. 准备容器

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
		ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
		ApplicationArguments applicationArguments, Banner printedBanner) {
	context.setEnvironment(environment);
	// 配置容器的类加载器、资源加载器、类型转换器
	postProcessApplicationContext(context);
	// 如果JVM允许AOT,则配置AOT相关的ApplicationContextInitializer
	// AOT(ahead of time)是在程序运行前将字节码编译成机器码,JIT(just in time)是程序边运行边将字节码编译成机器码。普通SpringBoot用的是JIT
	addAotGeneratedInitializerIfNecessary(this.initializers);
	// 1. 执行初始化器
	applyInitializers(context);
	listeners.contextPrepared(context);
	// 关闭引导上下文
	bootstrapContext.close(context);
	if (this.logStartupInfo) {
		logStartupInfo(context.getParent() == null);
		logStartupProfileInfo(context);
	}
	// Add boot specific singleton beans
	// beanFactory的类型是DefaultListableBeanFactory
	ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
	// 向bean工厂注册单例applicationArguments
	beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
	if (printedBanner != null) {
		beanFactory.registerSingleton("springBootBanner", printedBanner);
	}
	if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {
		// 配置是否允许循环依赖
		autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);
		if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {
			listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
	}
	if (this.lazyInitialization) {
		// 设置延迟加载
		context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
	}
	if (this.keepAlive) {
		// KeepAlive()对象额外启动一个非守护线程,避免`SpringBoot`因为非守护线程结束而关闭JVM
		context.addApplicationListener(new KeepAlive());
	}
	// PropertySourceOrderingBeanFactoryPostProcessor是对@PropertySource注解修饰的类进行排序
	context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
	if (!AotDetector.useGeneratedArtifacts()) {
		// 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);
}

1. 执行初始化器

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

SpringBoot默认的初始化器有7个。从上到下它们的功能分别是
0. 执行环境属性context.initializer.classes指定的初始化器。它的优先级最高。

  1. 向容器添加一个CachingMetadataReaderFactoryPostProcessor
  2. 初始化容器的ID。
  3. 向容器增加一个处理错误告警的BeanFactoryPostProcessor。
  4. RSocket是基于Reactive Streams的通信协议。
  5. 向容器配置server.port端口属性。
  6. 向容器中配置ConditionEvaluationReportListener。
    在这里插入图片描述

2.刷新容器


最终调用的是AbstractApplicationContext#refresh()方法。

private final Lock startupShutdownLock = new ReentrantLock();

public void refresh() throws BeansException, IllegalStateException {
	// startupShutdownLock锁是防止当前线程刷新容器,别的线程关闭容器。
	this.startupShutdownLock.lock();
	try {
		this.startupShutdownThread = Thread.currentThread();

		StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

		// Prepare this context for refreshing.
		// 1. 准备刷新
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		// 2. 重获容器
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		// 3. 配置容器
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			// 4. 容器子类添加后处理器
			postProcessBeanFactory(beanFactory);
			
			// 标记阶段
			StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
			// Invoke factory processors registered as beans in the context.
			
			// 5. 调用BeanFactory后处理器
			invokeBeanFactoryPostProcessors(beanFactory);
			// Register bean processors that intercept bean creation.
			// 6. 注册bean后处理器
			registerBeanPostProcessors(beanFactory);
			beanPostProcess.end();

			// Initialize message source for this context.
			// 向bean工厂注册一个名为`messageSource`的单例bean
			initMessageSource();

			// Initialize event multicaster for this context.
			// 向bean工厂注册一个名为`applicationEventMulticaster`的SimpleApplicationEventMulticaster对象
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			// 7. tomcat初始化
			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 (RuntimeException | Error 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 {
			contextRefresh.end();
		}
	}
	finally {
		this.startupShutdownThread = null;
		this.startupShutdownLock.unlock();
	}
}

1. 准备刷新

protected void prepareRefresh() {
	// Switch to active.
	this.startupDate = System.currentTimeMillis(); // startupDate的类型是`long`,标记容器启动时刻
	this.closed.set(false); // close的类型是`AtomicBoolean`,标记当前容器是否已就绪
	this.active.set(true); // active的类型是`AtomicBoolean`,标记当前容器是否活跃
	// 源码此处有log
	// Initialize any placeholder property sources in the context environment.
	// 初始化名称为`servletContextInitParams`的ServletContextPropertySource`,即初始化Servlet相关属性
	initPropertySources();

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

	// Store pre-refresh ApplicationListeners...
	// earlyApplicationListeners 刷新容器之前已存在的监听器
	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<>();
}

2. 重获容器

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	refreshBeanFactory();
	// 当前applicationContext是容器对象,但是包含了环境配置,事件发布器等等。而`getBeanFactory`返回的容器仅仅处理对象
	return getBeanFactory();
}
// GenericApplicationContext#refreshBeanFactory
protected final void refreshBeanFactory() throws IllegalStateException {
	// refreshed的类型是`AtomicBoolean`,代表容器正在刷新,cas表示容器只能刷新一次
	if (!this.refreshed.compareAndSet(false, true)) {
		throw new IllegalStateException(
				"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
	}
	// 容器的id是`application`
	this.beanFactory.setSerializationId(getId());
}

3. 配置容器

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	// Tell the internal bean factory to use the context's class loader etc.
	// 设置bean的类加载器,是`AppClassLoader`
	beanFactory.setBeanClassLoader(getClassLoader());
	// 设置SPEL解析器
	beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
	// 设置属性编辑器,将字符串属性转为java对象,比如将"false"字符串转为Boolean.False。
	beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

	// Configure the bean factory with context callbacks.
	// 配置bean后处理器。`ignoreDependencyInterface`表示容器不解析这些接口,不将接口的实现放入容器。
	//源码里是将这些接口放入`Set<Class<?>> ignoredDependencyInterfaces`。
	// 这些接口统一由`ApplicationContextAwareProcessor`处理。
	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.ignoreDependencyInterface(ApplicationStartupAware.class);

	// BeanFactory interface not registered as resolvable type in a plain factory.
	// MessageSource registered (and found for autowiring) as a bean.
	// 指定BeanFactory.class接口的容器对象是beanfactory
	// 源码里就是将`BeanFactory.class`和`beanFactory`放入`Map<Class<?>, Object> resolvableDependencies`。
	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.
	// 添加bean后处理器,ApplicationListenerDetector监听实现ApplicationListener接口的bean
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

	// Detect a LoadTimeWeaver and prepare for weaving, if found.
	// NativeDetector检测当前环境是否是GraalVM native镜像。
	if (!NativeDetector.inNativeImage() && 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()));
	}

	// Register default environment beans.
	// 向容器注册名为"environment"的单例ApplicationServletEnvironment对象
	if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
		beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
	}
	// 向容器注册名为"systemProperties"的单例Properties对象
	if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
		beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
	}
	// 向容器注册名为"systemEnvironment"的`UnmodifiableMap`对象
	if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
		beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
	}
	// 向容器注册名为"applicationStartup"的单例DefaultApplicationStartup对象
	if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
		beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
	}
}

4. 容器子类添加后处理器

ServletWebServerApplicationContext是容器实现类,它添加bean后处理器。WebApplicationContextServletContextAwareProcessor是向容器添加servletContext

// org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
	beanFactory.ignoreDependencyInterface(ServletContextAware.class);
	registerWebApplicationScopes();
}

5. 调用BeanFactory后处理器

最终调用的是PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法。后处理器分2种,一种是BeanDefinitionRegistryPostProcessors,处理BeanDefinitionRegistry中登记的BeanDefinitionBeanDefinition是bean的定义类,是对不同来源(Annotation注解,xml文件)的容器定义(scope, beanName)的抽象。容器根据定义类创建容器。一种是BeanFactoryPostProcessors,处理容器。
在这里插入图片描述
先看BeanDefinitionRegistryPostProcessors。首先处理PriorityOrdered接口,之后处理Ordered接口,其余的最后处理。
在这里插入图片描述
invokeBeanDefinitionRegistryPostProcessors方法让每个后处理器postProcessor调用自己的postProcessBeanDefinitionRegistry方法。其中有个org.springframework.context.annotation.ConfigurationClassPostProcessor将所有@Confuguration注解类解析成BeanDefinitionHolder

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

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
					.tag("postProcessor", postProcessor::toString);
			postProcessor.postProcessBeanDefinitionRegistry(registry);
			postProcessBeanDefRegistry.end();
		}
	}

BeanFactoryPostProcessors也是按照优先级进行处理。
在这里插入图片描述
处理结束后,删除缓存。

@Override
public void clearMetadataCache() {
	super.clearMetadataCache();
	this.mergedBeanDefinitionHolders.clear();
	clearByTypeCache();
}

在这里插入图片描述

6. 注册bean后处理器

在这里插入图片描述
registerBeanPostProcessors方法也是按照优先级注册bean后处理方法。这里的注册指的是将BeanPostProcessors放入容器,即abstractBeanFactory.addBeanPostProcessors(postProcessors)。而不是执行BeanPostProcessors,因为此时还没有创建bean。
在这里插入图片描述
最后将后处理器重新注册一遍。并且添加ApplicationListenerDetector容器后处理器。
在这里插入图片描述

7. tomcat初始化

onfresh()是交给容器子类自定义初始化,web容器在此配置web环境并且启动tomcat。
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到