day09 - Spring启动

Spring启动

前言:

本文摘要: Spring启动的核心流程围绕ApplicationContext的初始化展开,主要分为以下几个阶段:

准备阶段 - 初始化环境属性和监听器

BeanFactory创建 - 构建DefaultListableBeanFactory并加载BeanDefinitions

后处理阶段 - 执行BeanFactoryPostProcessors和注册BeanPostProcessors

功能初始化 - 设置国际化消息源、事件广播器等

Bean实例化 - 完成单例Bean的创建和初始化

完成阶段 - 发布上下文刷新事件

整个流程通过refresh()方法组织,包含同步控制、异常处理和缓存重置等保障机制,采用模板方法模式允许子类扩展特定步骤。核心在于BeanDefinition的加载解析和单例Bean的延迟初始化机制。

流程图如下:

1、Spring启动核心是ApplicationContext 的初始化过程,主要包含以下阶段:

1.构造BeanFactory对象
2.解析配置类,得到BeanDefiniton,并注册到BeanFactory中

a.解析@ComponentScan,完成扫描

b.解析@Bean

c...
3.Spring支持国际化,还要初始化initMessageSource对象
4.还支持事件,初始化 initApplicationEventMulticaster
5.子类模版方法
6.创建非懒加载的单例Bean,并存放单例池里面

a.三级缓存

b.include 、exclude
7.发布 ContextRefreshedEvent 事件

2、refresh() 核心代码讲解

org.springframework.context.support.AbstractApplicationContext#refresh

c 复制代码
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
       StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

       // Prepare this context for refreshing.
       // =============================== 准备阶段 ===================================
       // 1. 准备刷新上下文
       prepareRefresh();
       // 2.创建 / 获取BeanFactory
       ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
       
       // =============================== BeanFactory 准备阶段 ===================================
       // 3. 准备 BeanFactory (配置标准功能)
       prepareBeanFactory(beanFactory);

       try {
          // 4.允许子类对BeanFactory 进行后置处理          
          postProcessBeanFactory(beanFactory);
            
          StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");

          // =============================== BeanDefinition 加载阶段 ===================================
          // 5.调用BeanFactoryPostProcessors 
          invokeBeanFactoryPostProcessors(beanFactory);  // scanner.scan()

          // 6.注册BeanPostProcessor  
          registerBeanPostProcessors(beanFactory);

          beanPostProcess.end();
          
          //  =============================== 消息、事件、监听器初始化 ===================================
          // 7.初始化MessageSource(国际化)            
          initMessageSource();

          // 8.初始化事件广播器   
          initApplicationEventMulticaster();

          // 9.模版方法,子类可扩展            
          onRefresh();

          // 10.注册监听器 
          registerListeners();

          //  =============================== Bean 实例化阶段 ===================================
          // 11.完成BeanFactory初始化,实例化所有单例Bean
          finishBeanFactoryInitialization(beanFactory);

          // 12.完成刷新,发布 ContextRefreshedEvent
          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.
          // 13.销毁已创建的Bean 
          destroyBeans();

          // Reset 'active' flag.
          // 14. 取消已创建的Bean 
          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...
          // 15.重置Spring核心常见缓存
          resetCommonCaches();
          contextRefresh.end();
       }
    }
}

3、各阶段详解

1)准备刷新 - prepareRefresh()

c 复制代码
protected void prepareRefresh() {
    // 1.记录启动时间 
    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());
       }
    }
    // 2.初始化属性源 (property source)
    initPropertySources();

    // 3.验证必须属性
    getEnvironment().validateRequiredProperties();

    if (this.earlyApplicationListeners == null) {
       this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
       this.applicationListeners.clear();
       this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

    // 4.存储早期事件
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

2)获取BeanFactory - obtainFreshBeanFactory()

c 复制代码
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 1.刷新 BeanFactory
    refreshBeanFactory();
    // 2.获取新创建的BeanFactory
    return getBeanFactory();
}


// org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
       destroyBeans();
       closeBeanFactory();
    }
    try {
       // 1.创建 DefaultListableBeanFactory
       DefaultListableBeanFactory beanFactory = createBeanFactory();
       // 2.设置序列化ID
       beanFactory.setSerializationId(getId());
       customizeBeanFactory(beanFactory);
       // 3.加载BeanDefinitions(核心)
       loadBeanDefinitions(beanFactory);
       this.beanFactory = beanFactory;
    }
    catch (IOException ex) {
       throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

3)调用 BeanFactoryPostProcessor - invokeBeanFactoryPostProcessors

c 复制代码
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

  // 1.获取所有BeanFactoryPostProcessor  
  PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
  
  if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
       beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
       beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

4)注册 BeanPostProcessor - registerBeanPostProcessors()

c 复制代码
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    // 按优先级注册:
    // 1.BeanPostProcessorChecker
    // 2.PriorityOrdered 接口的 BeanPostProcessor
    // 3.Ordered 接口的 BeanPostProcessor
    // 4.普通的BeanPostProcessor
    // 5.内部使用的BeanPostProcessor 
}

5)完成BeanFactory初始化 - finishBeanFactoryInitialization()

c 复制代码
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 1.初始化 ConversionService (类型转换)
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
          beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
       beanFactory.setConversionService(
             beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }
    // 2.注册默认的字符串解析器
    if (!beanFactory.hasEmbeddedValueResolver()) {
       beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }

    // 3.初始化LoadTimeWeaverAware AOP 相关
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
       getBean(weaverAwareName);
    }
    // 4.停止使用临时类加载器
    beanFactory.setTempClassLoader(null);
    // 5.冻结配置 (不允许再修改BeanDefinition)
    beanFactory.freezeConfiguration();

    // 实例化非懒加载的单例Bean (最核心!!!)
    beanFactory.preInstantiateSingletons();
}

6)完成刷新 - finnishRefresh()

c 复制代码
protected void finishRefresh() {
    // 1.清除上下文资源缓存
    clearResourceCaches();
    // 2.初始化 LifecycleProcessor
    initLifecycleProcessor();
    // 3.启动 LifecycleProcessor
    getLifecycleProcessor().onRefresh();
    // 4.发布 ContextRefreshedEvent 事件
    publishEvent(new ContextRefreshedEvent(this));
    // 5.注册到 LiveBeansView 
    if (!NativeDetector.inNativeImage()) {
       LiveBeansView.registerApplicationContext(this);
    }
}

喜欢我的文章记得点个在看,或者点赞,持续更新中ing...

相关推荐
zs宝来了22 分钟前
Playwright 自动发布 CSDN 的完整实践
java
吴声子夜歌1 小时前
TypeScript——基础类型(三)
java·linux·typescript
GetcharZp2 小时前
Git 命令行太痛苦?这款 75k Star 的神级工具,让你告别“合并冲突”恐惧症!
后端
Victor3562 小时前
MongoDB(69)如何进行增量备份?
后端
Victor3563 小时前
MongoDB(70)如何使用副本集进行备份?
后端
DynamicsAgg3 小时前
企业数字化底座-k8s企业实践系列第二篇pod创建调度
java·容器·kubernetes
千寻girling3 小时前
面试官 : “ 说一下 Python 中的常用的 字符串和数组 的 方法有哪些 ? ”
人工智能·后端·python
森林里的程序猿猿3 小时前
并发设计模式
java·开发语言·jvm
222you3 小时前
四个主要的函数式接口
java·开发语言