关联博文:
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】resetCommon
重置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);