Spring 容器的初始化过程 | 启动流程


 

使用的spring源码版本 5.2.15.RELEASE

AbstractApplicationContext 是高级容器的基本实现类,此处围绕 AbstractApplicationContext 的 refresh() 方法进行讲述。

 

高级容器的构造方法

以常用的高级容器 ClassPathXmlApplicationContext 为例

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
	//设置父上下文
	super(parent);
	//设置配置文件位置
	setConfigLocations(configLocations);
	//加载或刷新配置,使配置文件生效
	if (refresh) {
		refresh();
	}
}

核心是调用父类的 refresh() 方法

 

refresh() 刷新容器

方法定义

ConfigurableApplicationContext 接口定义的 refresh()

/**
 * Load or refresh the persistent representation of the configuration, which might be from Java-based configuration, 
 * an XML file, a properties file, a relational database schema, or some other format.
 * 
 * As this is a startup method, it should destroy already created singletons if it fails, to avoid dangling resources. 
 * 
 * In other words, after invocation of this method, either all or no singletons at all should be instantiated.
 */
void refresh() throws BeansException, IllegalStateException;

refresh() 用于加载或刷新持久化配置,这些配置可以来自多种格式的配置文件、基于java代码的配置。

refresh() 是容器的启动方法,会重建应用上下文(ApplicationContext ),如果方法执行失败,会销毁所有已创建好的单例,即要么执行成功所有单例都已实例化,要么执行失败所有单例都没有实例化。

 

方法实现

AbstractApplicationContext 类实现的 refresh()

//操作容器的同步锁,在对容器进行refresh、destroy操作时使用
private final Object startupShutdownMonitor = new Object();

@Override
public void refresh() throws BeansException, IllegalStateException {

	//加锁,防止多线程同时对容器进行refresh、destroy操作
	synchronized (this.startupShutdownMonitor) {
		StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

		// 准备上下文的刷新
		prepareRefresh();

		// 获取最新的内置低级容器
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 准备要使用的BeanFactory实例
		prepareBeanFactory(beanFactory);

		try {
			//预留的扩展点
			//protected修饰的空方法,留给子类重写,可在容器创建、标准配置后做一些额外处理,比如注册一些特殊的BeanPostProcessor
			postProcessBeanFactory(beanFactory);

			//调用BeanFactory所有的后置处理器,用于修改beanFactory中的bean定义
			StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
			invokeBeanFactoryPostProcessors(beanFactory);

			//注册Bean的后置处理器
			registerBeanPostProcessors(beanFactory);
			beanPostProcess.end();

			//初始化 MessageSource
			initMessageSource();

			//初始化应用事件广播器
			initApplicationEventMulticaster();

			//protected修饰的空方法,作为扩展点预留给子类重写,用于初始化子类定义的一些特殊bean
			onRefresh();

			//注册应用监听器
			registerListeners();

			//初始化所有剩余单例(懒加载的除外)
			finishBeanFactoryInitialization(beanFactory);
			
			//完成刷新的最后操作
			finishRefresh();
		}

		catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}

			//销毁所有已创建单例
			destroyBeans();

			//将context的激活状态(active标识)重置为false
			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();
			contextRefresh.end();
		}
	}
}

 

refresh()方法流程图

在这里插入图片描述

 

 

refresh() 过程解析

prepareRefresh() 准备上下文的刷新

// 当前context开始启动的系统时间,ms
private long startupDate;

// 当前context是否处于激活状态
private final AtomicBoolean active = new AtomicBoolean();

//当前context是否已经关闭
private final AtomicBoolean closed = new AtomicBoolean();


//存储应用监听器
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();

//预刷新阶段(pre-refresh)要使用的应用监听器
private Set<ApplicationListener<?>> earlyApplicationListeners;

//在多播创建好之前,用于存储待发布的应用事件
private Set<ApplicationEvent> earlyApplicationEvents;


protected void prepareRefresh() {
	// 记录开始时间,设置 context (容器)状态
	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());
		}
	}

	// 初始化属性源
	// context environment中的property sources的值原本是占位符,这一步会把占位符替换为对应的实例
	initPropertySources();

	// 校验所需属性是否合法
	// 上一步是设置属性源,这一步是从属性源中解析得到属性值,并校验属性值是否合法
	getEnvironment().validateRequiredProperties();

	//初始化存储监听器的2个成员变量
	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);
	}

	//初始化存储早期应用事件的成员变量
	this.earlyApplicationEvents = new LinkedHashSet<>();
}

主要是给刷新上下文做一些准备工作,包括

  • 记录开始时间,设置 context|(容器)的状态、标识位
  • 初始化属性源,校验所需属性是否合法
  • 初始化存储应用监听器、存储早期应用事件的成员变量

 

obtainFreshBeanFactory() 获取最新的内置低级容器

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	//刷新内置的低级容器
	refreshBeanFactory();
	//返回刷新后的低级容器
	return getBeanFactory();
}

 

AbstractApplicationContext 只定义了 refreshBeanFactory() ,由子类提供实现,AbstractRefreshableApplicationContext 提供的实现如下

//内置的低级容器实例
@Nullable
private volatile DefaultListableBeanFactory beanFactory;

@Override
protected final void refreshBeanFactory() throws BeansException {
	//如果内部已经有BeanFactory实例,则先销毁其中所有的bean、关闭beanFactory
	if (hasBeanFactory()) {
		destroyBeans();
		closeBeanFactory();
	}
	try {
		//重新构建BeanFactory
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		//设置beanFactory的序列化id
		beanFactory.setSerializationId(getId());
		//对beanFactory应用自定义配置,有2个配置项:是否允许BeanDefinition覆盖、是否允许循环依赖
		customizeBeanFactory(beanFactory);
		//加载、解析、注册所有的BeanDefinition
		//这个类只提供了定义,由子类提供实现,包括xml、注解2种方式的实现
		//bean的加载、注册、创建、管理这些容器基础功能都是由BeanFactory提供,自然是注册到beanFactory中
		loadBeanDefinitions(beanFactory);
		//赋给成员变量
		this.beanFactory = beanFactory;
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

刷新低级容器这一步,完成了BeanDefinition的加载、解析、注册,十分重要,注意此时只是完成了BeanDefinition的注册,bean尚未初始化。

 

高级容器的基类是 ApplicationContext,ApplicationContext 继承自 BeanFactory,但实际上高级容器并未直接实现低级容器 BeanFactory 的功能,而是内置了一个低级容器实例来提供低级容器的功能,以成员变量的方式与低级容器进行交互,二者更接近组合,而非继承。

在 BeanFactory 的实现类中,DefaultListableBeanFactory 功能最为齐全,所以选择它作为低级容器的实现。DefaultListableBeanFactory 内置了一个map作为BeanDefinition注册表,存储所有bean的定义

//BeanDefinition的注册表,存储所有的BeanDefinition,key是beanName
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

 

prepareBeanFactory() 准备beanFactory

主要是对上一步创建的beanFactory实例进行标准化配置,配置 beanFactory的标准上下文特征

/**
 * Configure the factory's standard context characteristics,
 * such as the context's ClassLoader and post-processors.
 */
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	// Tell the internal bean factory to use the context's class loader etc.
	beanFactory.setBeanClassLoader(getClassLoader());
	if (!shouldIgnoreSpel) {
		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.ignoreDependencyInterface(ApplicationStartupAware.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));

	// Detect a LoadTimeWeaver and prepare for weaving, if found.
	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.
	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());
	}
	if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
		beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
	}
}

 

finishBeanFactoryInitialization() 初始化所有剩余单例

实际是调用 DefaultListableBeanFactory 的 preInstantiateSingletons() 方法

@Override
public void preInstantiateSingletons() throws BeansException {
	if (logger.isTraceEnabled()) {
		logger.trace("Pre-instantiating singletons in " + this);
	}

	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

	//遍历所有的 BeanDefinition
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		//如果bean不是抽象的、是单例、不是懒加载的,则进行实例化
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			//不管是FactoryBean方式创建的单例,还是普通的单例,都是通过getBean()方法获取的实例
			if (isFactoryBean(beanName)) {
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceof FactoryBean) {
					FactoryBean<?> factory = (FactoryBean<?>) bean;
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(
								(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
								getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						//获取实例
						getBean(beanName);
					}
				}
			}
			else {
				//获取实例
				getBean(beanName);
			}
		}
	}

	// Trigger post-initialization callback for all applicable beans...
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		if (singletonInstance instanceof SmartInitializingSingleton) {
			StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
					.tag("beanName", beanName);
			SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					smartSingleton.afterSingletonsInstantiated();
					return null;
				}, getAccessControlContext());
			}
			else {
				smartSingleton.afterSingletonsInstantiated();
			}
			smartInitialize.end();
		}
	}
}

实质是通过 beanFactory的getBean() 创建所有剩余单例(懒加载的除外)的实例,FactoryBean方式的单例也会在这一步创建。

 

finishRefresh() 完成刷新的最后操作

protected void finishRefresh() {
		//清除缓存的类加载器加载的资源
		clearResourceCaches();

		//创建生命周期管理器 LifecycleProcessor 实例,放到容器中
		//如果beanFactory中有对应的bean定义,则执行 this.xxx = beanFactory.getBean();   getBean()创建实例放到容器中,并赋给高级容器对应的成员变量
		//否则直接new一个实例,beanFactory.registerSingleton() 注册到容器中
		initLifecycleProcessor();

		//给容器中的所有单例添加生命周期管理
		getLifecycleProcessor().onRefresh();

		//广播上下文已刷新事件 ContextRefreshedEvent
		publishEvent(new ContextRefreshedEvent(this));

		//注册应用上下文
		LiveBeansView.registerApplicationContext(this);
	}

 

BeanFactoryPostProcessor、BeanPostProcessor的区别

都是后置处理器(PostProcessor),用于后续的加工处理,区别如下

  • 加工对象不同:BeanFactoryPostProcessor用于对BeanFactory实例进行加工处理,BeanPostProcessor用于对Bean实例进行加工处理
  • 作用时机不同:BeanFactoryPostProcessor作用于spring容器加载bean定义之后、bean实例化之前,BeanPostProcessor作用于bean的初始化阶段。

 

spring容器的扩展点

spring容器(AbstractApplicationContext)给子类预留了2个扩展点,都是protected修饰的空方法,留给子类重写

  • postProcessBeanFactory() :可在容器创建、标准配置后做一些额外处理,比如注册一些特殊的BeanPostProcessor
  • onRefresh():在创建bean实例阶段调用,用于初始化一些特殊的bean

 

spring容器的生命周期

高级容器集成了 Lifecycle 生命周期管理,本身也会作为bean放到容器中,会处于生命周期管理器的管理下。

spring容器的生命周期与上下文的4个事件息息相关。
 

1、应用启动时调用高级容器的 refresh() 方法创建、刷新容器

  • 在 refresh() 的 finishRefresh() 阶段会创建生命周期管理器,调用容器的start()方法开启容器,添加生命周期管理,发布上下文开始事件 ContextStartedEvent
  • 在refresh() 刷新上下文完成后,会发布上下文已刷新事件 ContextRefreshedEvent
     

2、容器刷新完成后一直处于运行(running)阶段,或者说上下文一直处于激活(active)阶段
 

3、终止jvm或调用高级容器的close()方法时,容器关闭

  • 关闭容器时会调用容器的stop()方法,终止生命周期管理,发布上下文已停止事件 ContextStoppedEvent
  • 容器关闭完成后会发布上下文已关闭事件 ContextClosedEvent

版权声明:本文为chy_18883701161原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。