[读书笔记]AbstractApplicationContext中refresh方法详解

简介: [读书笔记]AbstractApplicationContext中refresh方法详解

关联博文:

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);
目录
相关文章
|
人工智能 自然语言处理 搜索推荐
阿里云百炼产品月刊【2025年2月】
本期⽉刊主要亮点包括推出全新多模态理解生成大模型通义千问Omni系列,支持文本、图像、语音和视频输入,提供流式输出和四种自然对话音色,新增高性价比图生视频模型wanx2.1-i2v-turbo,生成速度快,耗时仅为旧模型的三分之一。此外,qwen-plus采购季资源包上线,享受8.6折优惠;qwen-max模型降价88%,极大降低使用门槛。智能体应用和工作流应用现支持DeepSeek系列模型,增强私有知识库问答和任务型、对话型工作流构建能力。文件交互和批量节点功能进一步提升应用灵活性和实用性。本月还推出了AI实训营和应用开发实训营,提供手把手AI课程和企业级多模态应用构建指导。
1016 0
|
Android开发
Android 常见对话框的简单使用(提示信息对话框、单选多选对话框、自定义对话框)
Android 常见对话框的简单使用(提示信息对话框、单选多选对话框、自定义对话框)
539 0
Android 常见对话框的简单使用(提示信息对话框、单选多选对话框、自定义对话框)
|
iOS开发 MacOS
mac bookpro m1 笔记本关闭键盘屏幕 禁用键盘屏幕使用 键盘屏幕误触 Touch Bar禁用 禁用MacBook-Pro的触摸栏
mac bookpro m1 笔记本关闭键盘屏幕 禁用键盘屏幕使用 键盘屏幕误触 Touch Bar禁用 禁用MacBook-Pro的触摸栏
439 3
|
9月前
|
SQL Unix OLAP
ClickHouse安装教程:开启你的列式数据库之旅
ClickHouse 是一个高性能的列式数据库管理系统,适用于在线分析处理(OLAP)。本文介绍了 ClickHouse 的基本使用步骤,包括下载二进制文件、安装应用、启动服务器和客户端、创建表、插入数据以及查询新表。还提到了图形客户端 DBeaver 的使用,使操作更加直观。通过这些步骤,用户可以快速上手并利用 ClickHouse 的强大性能进行数据分析。
996 4
|
12月前
|
设计模式 Java
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
|
负载均衡 安全 网络协议
突发!亚洲游戏行业遭遇史上最大黑客 DDoS 攻击
游戏行业遭受频繁DDoS攻击,导致服务中断,例如欧洲国家安道尔全国近断网半小时。黑客利用低成本的DDoS手段勒索,尤其是针对中日韩印的手游市场。最常见的攻击方式是UDP洪水。防御措施包括使用硬件防火墙、抗D盾、负载均衡、SCDN流量清洗和分布式集群防御。游戏公司需平衡成本与安全,以确保服务稳定和玩家体验。在中国,此类攻击属犯罪行为,最高可判处有期徒刑。
|
Java Spring 容器
Spring系列(五):@Lazy懒加载注解用法介绍
@Lazy 懒加载注解的概念 SpringIoC容器会在启动的时候实例化所有单实例 bean 。如果我们想要实现 Spring 在启动的时候延迟加载 bean,即在首次调用bean的时候再去执行初始化,就可以使用 @Lazy 注解来解决这个问题
Spring系列(五):@Lazy懒加载注解用法介绍
|
NoSQL Java 数据处理
Redis和Spring Boot的绝佳组合:Lua脚本的黑科技
Redis和Spring Boot的绝佳组合:Lua脚本的黑科技
265 0
|
SQL 存储 Java
【问题处理】—— 一次内存溢出(OutOfMemoryError)实战排查
【问题处理】—— 一次内存溢出(OutOfMemoryError)实战排查
401 0
|
XML 缓存 Java
你尝试过在mybatis某个mapper上同时配置<cache/>和<cache-ref/>吗?
你尝试过在mybatis某个mapper上同时配置<cache/>和<cache-ref/>吗?
194 0

热门文章

最新文章