当前位置: 首页 > news >正文

Spring源码解析 - SpringApplication run流程-prepareContext源码分析

prepareContext源码分析

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {// 1️⃣ 把已准备好的 Environment 设置到 ApplicationContext 中context.setEnvironment(environment);// 2️⃣ 后置处理 ApplicationContext(可被子类覆盖,做额外定制)postProcessApplicationContext(context);// 3️⃣ 执行所有 ApplicationContextInitializer(在 refresh 之前运行)// SpringApplication 初始化setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));的set//钩子函数applyInitializers(context);// 4️⃣ 生命周期事件:contextPrepared —— ApplicationContext 已创建但未 refreshlisteners.contextPrepared(context);// 5️⃣ 关闭早期 BootstrapContext,释放临时资源// 实现bootstrapRegistryInitializers这个钩子注册的bean,将其移动到真正的 BeanFactorybootstrapContext.close(context);// 6️⃣ 如果开启启动信息日志,打印应用名、PID、profile 等if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// 7️⃣ 获取 BeanFactory,准备注册单例 BeanConfigurableListableBeanFactory beanFactory = context.getBeanFactory();// 8️⃣ 把命令行参数包装成 Bean 注册到容器(供开发者使用 @Autowired 注入获取applicationArguments)beanFactory.registerSingleton("springApplicationArguments", applicationArguments);// 9️⃣ 如果前面打印了 Banner,也把 Banner 注册成单例 Beanif (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}// 🔟 根据配置决定是否允许循环依赖if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);}// 1️⃣1️⃣ 根据配置决定是否允许 BeanDefinition 覆盖if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}// 1️⃣2️⃣ 如果启用懒加载,添加对应的 BeanFactoryPostProcessorif (this.lazyInitialization) {context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}// 1️⃣3️⃣ 添加 PropertySource 排序处理器,保证外部配置优先级正确context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));// 1️⃣4️⃣ 获取启动源(主类、@SpringBootApplication、@Import 等)Set<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");// 1️⃣5️⃣ 真正加载启动源(主类、配置类等)到容器load(context, sources.toArray(new Object[0]));// 1️⃣6️⃣ 生命周期事件:contextLoaded —— BeanDefinition 已加载完毕,等待 refreshlisteners.contextLoaded(context);
}

prepareContext重要流程分析

postProcessApplicationContext分析

postProcessApplicationContext源码解析

① 注入自定义 BeanNameGenerator
if (this.beanNameGenerator != null) {//由于之前context是new AnnotationConfigServletWebServerApplicationContext(),使用空构造//会调用父类的public GenericApplicationContext() {//	this.beanFactory = new DefaultListableBeanFactory();//}//通过DefaultListableBeanFactory的super.registerSingleton(beanName, singletonObject);将其注册进单例bean里面,没有bean的创建流程//    @Override//    public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {//        super.registerSingleton(beanName, singletonObject);//        updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));//        clearByTypeCache();//    }context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,this.beanNameGenerator);
}
  • 场景:当你显式给 SpringApplication.setBeanNameGenerator(...) 传了自定义实现时。
  • 作用:把它注册成 单例 Bean org.springframework.context.annotation.internalConfigurationBeanNameGenerator
    之后 @Configuration@Component 等扫描时就会用它来决定 Bean 名称。
② 注入自定义 ResourceLoader
if (this.resourceLoader != null) {if (context instanceof GenericApplicationContext) {((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);}if (context instanceof DefaultResourceLoader) {((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());}
}
  • 场景SpringApplication.setResourceLoader(...) 传入过自定义 ResourceLoader(例如读取 jar 外部配置)。
  • 作用
    • GenericApplicationContext:替换整个容器的 资源解析器
    • DefaultResourceLoader:确保 类加载器 与自定义 ResourceLoader 保持一致,避免 classpath 解析错误。
③ 把 Environment 的 ConversionService 塞进 BeanFactory
if (this.addConversionService) {context.getBeanFactory().setConversionService(context.getEnvironment().getConversionService());
}
  • 场景addConversionService 默认为 true
  • 作用:把 统一类型转换服务 注册进 BeanFactory,后续:
    • @Value("${port:8080}") int port
    • @ConfigurationProperties 绑定
    • 都能用同一套 ConversionService 完成字符串 → 目标类型的转换。

✅ 一句话总结
postProcessApplicationContext 是一个 “启动前置钩子”
默认实现把 BeanNameGenerator、ResourceLoader、ConversionService 这三个基础设施一次性塞进容器,
确保后续注解扫描、资源加载、属性绑定都能按预期工作。


http://www.lryc.cn/news/617547.html

相关文章:

  • 了解不同电磁仿真类型中的电容报告
  • 某地渣库边坡自动化监测服务项目
  • GDB调试 core dump 文件与栈溢出分析
  • 农业气象站的应用场景拓展
  • 学习观察和行动:机器人操作中任务-觉察的视图规划
  • 2025年渗透测试面试题总结-13(题目+回答)
  • Python训练营打卡 DAY 33 MLP神经网络的训练
  • 首涂模板第45套主题2.0修正版苹果CMS模板奇艺主题二开源码
  • 【AxureMost落葵网】CRM客户关系管理原型系统-免费
  • MD5:理解MD5 / MD5核心特性 / MD5 在前端开发中的常见用途 / 在线生成MD5 / js-md5
  • 【Kafka系列】第三篇| 在哪些场景下会选择使用 Kafka?
  • 【车联网kafka】Kafka核心架构与实战经验(第三篇)
  • 钓鱼鱼饵制作的方式
  • Go 多进程编程-同步
  • 免费好用的数字人API
  • synchronized 、volatile 以及 ReentrantLockReentrantLock 的区别
  • monorepo架构设计方案
  • 小白入门指南:Edge SCDN 轻松上手
  • 【NOI】落谷2025/08/10 SCP-J 模拟测试 第10题 求构成三角形的概率
  • qss基础
  • Godot ------ 平滑拖动02
  • 机器学习第九课之DBSCAN算法
  • 智慧工地:以三大监测技术筑牢安全屏障
  • (Arxiv-2025)Phantom-Data:迈向通用的主体一致性视频生成数据集
  • Qwen 3 架构深度解析:混合推理、MoE创新与开源生态的全面突破
  • 工业智造新引擎:BRAV-7135赋能自动化产线升级
  • 第八篇:交互入门:鼠标拾取物体
  • 可视化+自动化:招聘管理看板软件的核心技术架构解析
  • 网络资源模板--基于Android Studio 实现的手绘板App
  • Docker部署MySQL完整指南:从入门到实践