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...

相关推荐
yixin1231 小时前
Spring 多实例注入
java·后端·spring
zsyf19871 小时前
spring security 超详细使用教程(接入springboot、前后端分离)
java·spring boot·spring
小同志001 小时前
网络原理 -KTTP/HTTPS(五) --认识响应“报头“(header) / “正⽂“(body)
java·网络·网络协议·http·https
heartbeat..1 小时前
Java 微服务初学者入门指南(CSDN 博客版)
java·运维·微服务·学习笔记·入门
一 乐2 小时前
健身房预约|基于java+ vue健身房预约小程序系统(源码+数据库+文档)
java·vue.js·spring boot·小程序·论文·毕设·健身房预约小程序
xdpcxq10292 小时前
Flask - 常见应用部署方案
后端·python·flask
望舒5132 小时前
代码随想录day32,动态规划part1
java·算法·leetcode·动态规划
Ivanqhz2 小时前
数据流分析的核心格(Lattice)系统
开发语言·javascript·后端·python·算法·蓝桥杯·rust
麻辣香蝈蝈3 小时前
【入门】职场如何沟通以及开发一个功能
java