从getBean()分析BeanFactory和ApplicationContext
本文说了哪些问题:
- BeanFactory 是啥
- ApplicationContext 是啥
- 什么时候去实例化一个 bean, BeanFactory 和 ApplicationContext 实例化 bean 都是在什么时候
一个 Bean 什么时候被初始化
任何一个 Bean, 都是在 getBean () 的时候被初始化的.BeanFactory 需要字节手动调用 getbean 获取才会创建, 而 ApplicationContext 则是使用
那为什么还要区分 BeanFactory 呢?
这是因为 BeanFactory 初始化有这几个阶段
Resource resource = new ClassPathResource("applicationContext.xml");
// 创建一个DefaultListableBeanFactory
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
BeanDefinitionReader beanDefinitionReader = new
// 创建XmlBeanDefinitonReder
XmlBeanDefinitionReader(defaultListableBeanFactory);
// loadBeanDefiniton
beanDefinitionReader.loadBeanDefinitions(resource);
本文不过多解释其他不重要的知识点, 着重于**文章题目**的解释
观点纠正:
注意了, loadBeanDefintions 方法并不会去实例化 Bean, 这里只是把我们定义的 Bean 的信息, 封装成 BeanDefiniton 而已, 并不会去实例化.
对于创建 Bean, 在 beanFactory 中, 则是以我们手动调用 getBean 为准, 才会去创建 Bean
很多时候, 我们使用 Spring 的时候, 并没有去手动的创建, bean 也都存在了啊??
这是什么情况.
这是因为 ApplicationContext 的预加载机制, 会加载所有的单例的非抽象的以及非懒加载的 Bean
看见懒加载, 那么懒加载的 bean 啥时候加载?? 还是 getBean.
然后你再猜猜预加载机制是通过什么方法来进行预加载的??
还是 getBean ()方法
先来看看 ClassPathXmlAplicationContext 的注释, ClassPathXmlApplicationContext 在容器初始化的时候, 就调用了父类的 refersh ()方法, 然后在其中的 finishBeanFactoryInitialization(beanFactory) 方法 ----> 调用了 beanFactory.preInstantiateSingletons(); 这一行关键代码
public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 创建出所有的单实例Bean;Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //开始解析文件的时候每一个bean标签被解析封装成一个BeanDefinitionif (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) { //如果是FactoryBean则执行下面逻辑Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); //得到HelloFactoryif (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else { //不是FactoryBean则执行这个,普通的单实例非懒加载bean的创建getBean(beanName); //}}}// 触发 post-initialization 逻辑; Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}smartInitialize.end();}}}public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 创建出所有的单实例Bean;Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //开始解析文件的时候每一个bean标签被解析封装成一个BeanDefinitionif (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) { //如果是FactoryBean则执行下面逻辑// FACTORY_BEAN_PREFIX == '&'Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); //得到HelloFactoryif (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else { //不是FactoryBean则执行这个,普通的单实例非懒加载bean的创建getBean(beanName); //}}}// 触发 post-initialization 逻辑; Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}smartInitialize.end();}}}public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 创建出所有的单实例Bean;Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //开始解析文件的时候每一个bean标签被解析封装成一个BeanDefinitionif (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) { //如果是FactoryBean则执行下面逻辑Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); //得到HelloFactoryif (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else { //不是FactoryBean则执行这个,普通的单实例非懒加载bean的创建getBean(beanName); //}}}// 触发 post-initialization 逻辑; Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}smartInitialize.end();}}}
注意, 这里是预加载, 预加载会加载所有的非懒加载的的单例的非抽象的 bean .而懒加载, 其实也是在 getBean ()的时候才会加载的.
延申
你有没有了解 BeanPostProcessor?
BeanPostProcessor 本质上也是 bean
参考一下 refresh () 的 registerBeanPostProcessors(beanFactory);
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);}
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {// WARNING: Although it may appear that the body of this method can be easily// refactored to avoid the use of multiple loops and multiple lists, the use// of multiple lists and multiple passes over the names of processors is// intentional. We must ensure that we honor the contracts for PriorityOrdered// and Ordered processors. Specifically, we must NOT cause processors to be// instantiated (via getBean() invocations) or registered in the ApplicationContext// in the wrong order.//// Before submitting a pull request (PR) to change this method, please review the// list of all declined PRs involving changes to PostProcessorRegistrationDelegate// to ensure that your proposal does not result in a breaking change:// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22//获取到容器中所有的 BeanPostProcessor; Bean的后置处理器String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);// Register BeanPostProcessorChecker that logs an info message when// a bean is created during BeanPostProcessor instantiation, i.e. when// a bean is not eligible for getting processed by all BeanPostProcessors.int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// Separate between BeanPostProcessors that implement PriorityOrdered,// Ordered, and the rest.List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();List<String> orderedPostProcessorNames = new ArrayList<>();List<String> nonOrderedPostProcessorNames = new ArrayList<>();for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { //获取所有实现了 PriorityOrdered 的 BeanPostProcessorBeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);priorityOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}//首先,注册所有的实现了 PriorityOrdered 的 BeanPostProcessor ; First, register the BeanPostProcessors that implement PriorityOrdered.sortPostProcessors(priorityOrderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);//接下来,注册所有的实现了 Ordered 的 BeanPostProcessor Next, register the BeanPostProcessors that implement Ordered.List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());for (String ppName : orderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); //获取后置处理器对象orderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}sortPostProcessors(orderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, orderedPostProcessors);// 最后,注册所有普通的 BeanPostProcessor ;Now, register all regular BeanPostProcessors.List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());for (String ppName : nonOrderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); //从容器中获取这个组件nonOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);//最后,重新注册所有internal的BeanPostProcessors Finally, re-register all internal BeanPostProcessors.sortPostProcessors(internalPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, internalPostProcessors);// 重新注册一下这个后置处理器 Re-register post-processor for detecting inner beans as ApplicationListeners,// 把他放到后置处理器的最后一位; moving it to the end of the processor chain (for picking up proxies etc).beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));}
相关文章:
从getBean()分析BeanFactory和ApplicationContext
本文说了哪些问题: BeanFactory 是啥ApplicationContext 是啥什么时候去实例化一个 bean, BeanFactory 和 ApplicationContext 实例化 bean 都是在什么时候 一个 Bean 什么时候被初始化 任何一个 Bean, 都是在 getBean () 的时候被初始化的.BeanFactory 需要字节手动调用 getb…...
详解Redis的主从同步原理
前言 Redis为了保证服务高可用,其中一种实现就是主从模式,即一个Redis服务端作为主节点,若干个Redis服务端作为主节点的从节点,从而实现即使某个服务端不可用时,也不会影响Redis服务的正常使用。本篇文章将对主从模式…...
前端项目上线后,浏览器缓存未刷新问题
文章目录问题背景一、解决办法二、实现原理关于缓存强缓存协商缓存刷新页面对浏览器的影响总结问题背景 前端页面开发测试完,要进行上线,某些页面上传更新到服务器之后,浏览器并没有更新,渲染的还是老页面。这是因为浏览器读了缓存…...
Vulnhub系列:Raven 1
该篇为Vulnhub系列靶机渗透,本次靶机存在4个flag。下面开始我们今天的渗透之旅。Raven靶机有很多种思路,我将对其进行一一整理。首先进行信息收集,利用arp-scan和nmap,进行靶机的ip及端口扫描发现了22、80、111端口。下面访问80端…...
MybatisPlus------多数据源环境(十一)
MybatisPlus------多数据源环境(十一) 生产环境中常常会存在多个数据源。 比如读写分离、一主多从、混合模式等等。 首先再pom文件中需要引入依赖: 多数据源所需要使用到的依赖 <!-- 多数据源所需要使用到的依赖--><depend…...
Tomcat+IDEA+Servlet能显示页面但提交form表单出现404问题
问题: 当我们使用tomcat启动,然后输入对应的url路径时候,能出现该html的页面,但提交表单后,却出现了404的问题,这时候我就很疑惑了....然后开始慢慢分析。 思路: 首先我们得知道404状态码是什…...
【蓝桥杯集训16】多源汇求最短路——Floyd算法(2 / 2)
目录 Floyd求最短路模板 4074. 铁路与公路 - floyd 脑筋急转弯 Floyd求最短路模板 活动 - AcWing 题目: 给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,边权可能为负数。 再给定 k 个询问,每个询问包含两个整数 x 和…...
simulink stateflow 状态机
系列文章目录 文章目录系列文章目录前言一、基操二、stateflow 数据三、chart动作四、chart的执行五、flow chart / junction六、状态机中的函数 Stateflow Functions七、chart层次结构八、案例——吸尘器机器人的驱动模式前言 一、基操 在tooltrip中选择DEBUG,通过…...
水库大坝安全监测的主要坝体类型介绍
水电站和水库大坝安全的分类中有重力坝、土石坝等不同的大坝形式。就在这里详细水库大坝安全监测按照建造形式,基本上可以分为三类:重力坝、土石坝和拱坝。 (1)重力坝 重力坝,顾名思义就是利用自身重力来维持坝体稳定…...
物理层概述(二)重点
目录前言编码与调制(1)基带信号与宽带信号编码与调制编码与调制(2)数字数据编码为数字信号非归零编码【NRZ】曼斯特编码差分曼彻斯特编码数字数据调制为模拟信号模拟数据如何编码为数字信号模拟数据调制为模拟信号物理层传输介质导…...
成都待慕电商:抖音极速版商品卡免佣扶持政策规则
新规,抖音极速版推出商品卡免佣扶持政策规则,本次抖音规则如何规定?具体往下看:一、政策简介1.1政策介绍为了更好地满足用户消费需求,丰富商家经营模式,降低商家经营成本,现平台针对商品卡场景推…...
青岛双软认定标准
软件企业的认定是有一定的标准的,需要满足以下这些条件:1、在我国境内依法设立了企业法人的企业;2、以计算机软件开发生产、系统集成、应用服务和其他相应技术服务为经营业务和主要经营收入;3、具有一种以上由本企业开发或由本企业…...
【00后卷王秘籍】python自动化测试—Python自动化框架及工具
1 、概述 手续的关于测试的方法论,都是建立在之前的文章里面提到的观点: 功能测试不建议做自动化 接口测试性价比最高 接口测试可以做自动化 后面所谈到的 测试自动化 也将围绕着 接口自动化 来介绍。 本系列选择的测试语言是 python 脚本语言。由于其…...
MySQL数据库基本操作
DDL 1、DDL解释 DDL(Data Definition Language),数据定义语言,该语言部分包括以下内容: 对数据库的常用操作 对表结构的常用操作 修改表结构1、对数据库的常用操作 2、对表结构的常用操作-创建表 创建表格式 3、对表结构的常用操作-创建表…...
2023年最新的站内SEO指南:如何通过关键词优化提高网站排名
SEO或搜索引擎优化是指通过改善网站的内部和外部元素,以获得更好的自然搜索引擎排名和更多的网站流量。 链接建设和外链是SEO的重要组成部分,因为它们可以提高网站的权威性和可信度,从而使其在搜索引擎中排名更高。 在此指南中,…...
【Java】Java环开发环境安装
Java环开发环境安装 简介: 如果要从事Java编程,则需要安装JDK,如果仅仅是运行一款Java程序则JRE就满足要求。 Java的安装包分为两类 一类是JRE其就是一个独立的Java运行环境; 一类是JDK其是Java的开发环境,不过在JDK…...
[蓝桥杯] 枚举、模拟和排列问题
文章目录 一、连号区间数 1、1 题目描述 1、2 题解关键思路与解答 二、递增三元组 2、1 题目描述 2、2 题解关键思路与解答 三、错误票据 3、1 题目描述 3、2 题解关键思路与解答 四、回文日期 4、1 题目描述 4、2 题解关键思路与解答 五、归并排序 标题:蓝桥杯——…...
C++基础了解-02-C++ 数据类型
C 数据类型 一、C 数据类型 使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当创建一个变量时,就会在内存中保留一些空间。 可能需要存储各种数据类型(比如字符型、宽…...
关于MSVCR100.dll、MSVCR100d.dll、Msvcp100.dll、abort()R6010等故障模块排查及解决方法
一、常见故障介绍 最近在开发相机项目(项目细节由于公司保密就不介绍了),程序运行5个来月以来首次出现msvcr100.dll故障等问题,于是乎开始了分析之路,按照度娘上的一顿操作,期间也是出现了各种不一样的问…...
【蓝桥杯集训·每日一题】AcWing 3305. 作物杂交
文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴Spfa算法一、题目 1、原题链接 3305. 作物杂交 2、题目描述 作物杂交是作物栽培中重要的一步。 已知有 N 种作物 (编号 1 至 N),第 i 种作物从播种到成熟的时间…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
