关联博文:
AbstractApplicationContext中refresh方法详解
Spring中refresh分析之prepareRefresh方法详解
Spring中refresh分析之obtainFreshBeanFactory方法详解
Spring中refresh分析之prepareBeanFactory方法详解
Spring中refresh分析之postProcessBeanFactory方法详解
Spring中refresh分析之invokeBeanFactoryPostProcessors方法详解
Spring中refresh分析之registerBeanPostProcessors方法详解
Spring中refresh分析之initMessageSource方法详解
Spring中refresh分析之initApplicationEventMulticaster方法详解
Spring中refresh分析之onRefresh方法详解
Spring中refresh分析之registerListeners方法详解
Spring中refresh分析之finishBeanFactoryInitialization方法详解
Spring中refresh分析之finishRefresh方法详解

Spring IoC容器对Bean定义资源的载入是从refresh()函数开始的,refresh()是一个模板方法,refresh()方法的作用是在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。

refresh的作用类似于对IoC容器的重启,在新建立好的容器中对容器进行初始化,对Bean定义资源进行载入

refresh()方法主要为IoC容器Bean的生命周期管理提供条件,Spring IoC容器载入Bean定义资源文件从其子类容器的refreshBeanFactory()方法启动,所以整个refresh()中ConfigurableListableBeanFactory beanFactory =obtainFreshBeanFactory();”这句以后代码的都是注册容器的信息源和生命周期事件,载入过程就是从这句代码启动。

本文开始,我们将分析refresh的系列方法。

【1】方法概览

AbstractApplicationContext 的refresh方法如下所示:

@Override
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.
			//为了防止Bean资源占用,在异常处理中销毁已经在前面过程中生成的单件Bean
			destroyBeans();

			// Reset 'active' flag.
			//重置 active 标识
			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();
		}
	}
}

方法解释如下:

  • ① 准备刷新的上下文环境;
  • ② 获取到应用上下文维护的beanFactory,默认是DefaultListableBeanFactory。并设置刷新标志refreshed为true
  • ③ 对beanFactory做了一些基础设置的配置,比如BeanClassLoader、BeanExpressionResolver、ApplicationContextAwareProcessor、ApplicationListenerDetector监听器检测器以及默认的环境信息bean。并设置了哪些不需要自动注入以及哪些已经解析过可以直接使用。
  • ④ BeanFactory的后置处理;
  • ⑤ 注册并调用BeanFactoryPostProcessor,扫描获取BeanDefinition;
  • ⑥ 注册BeanPostProcessor到BeanFactory;
  • ⑦ 初始化MessageSource消息源;
  • ⑧ 初始化事件广播器;
  • ⑨ 初始化themeSource并创建WebServer;
  • ⑩ 检查监听bean并将这些bean向容器中注册
  • (11) 初始化所有non-lazy-init bean,比如我们的controller、service、mapper等;
  • (12) 发布容器事件,结束Refresh过程
  • (13) 重置Spring核心中的常见内省缓存,因为我们可能不再需要单例bean的元数据。。。

【2】异常捕捉中的两个方法

① destroyBeans

这是一个模板方法,销毁所有上下文管理的bean。默认实现是销毁上下文缓存的所有单例bean,通过触发DisposableBean.destroy()方法或者指定的具体destroy-method。可以重写以在标准单例销毁之前或之后添加特定于上下文的bean销毁步骤,如果上下文的BeanFactory仍处于活动状态。

protected void destroyBeans() {
	getBeanFactory().destroySingletons();
}

DefaultListableBeanFactory的销毁实例方法如下所示,其首先触发父类DefaultSingletonBeanRegistry的销毁方法,然后清空Set<String> manualSingletonNames

@Override
public void destroySingletons() {
	super.destroySingletons();
	updateManualSingletonNames(Set::clear, set -> !set.isEmpty());
	clearByTypeCache();
}

DefaultSingletonBeanRegistry的destroySingletons方法。

public void destroySingletons() {
	if (logger.isTraceEnabled()) {
		logger.trace("Destroying singletons in " + this);
	}
	synchronized (this.singletonObjects) {
	//设置状态
		this.singletonsCurrentlyInDestruction = true;
	}

	String[] disposableBeanNames;
	synchronized (this.disposableBeans) {
		disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
	}
	// 循环遍历销毁每一个disposableBean
	for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
		destroySingleton(disposableBeanNames[i]);
	}
	//清空集合
	this.containedBeanMap.clear();
	this.dependentBeanMap.clear();
	this.dependenciesForBeanMap.clear();
	// 清空缓存 包括一级、二级、三级以及registeredSingletons
	clearSingletonCache();
}

② cancelRefresh

这个方法简单,就只重置标志:

  • 将beanFactory的SerializationId置为null
  • active设置为false

【3】resetCommonCaches

重置Spring核心中的常见内省缓存,因为我们可能不再需要单例bean的元数据。

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

ReflectionUtils.clearCache如下所示:

public static void clearCache() {
	declaredMethodsCache.clear();
	declaredFieldsCache.clear();
}

AnnotationUtils.clearCache如下所示:

public static void clearCache() {
	AnnotationTypeMappings.clearCache();
	AnnotationsScanner.clearCache();
}

ResolvableType.clearCache如下所示:

public static void clearCache() {
	cache.clear();
	SerializableTypeWrapper.cache.clear();
}

private static final ConcurrentReferenceHashMap<ResolvableType, ResolvableType> cache =
new ConcurrentReferenceHashMap<>(256);
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐