头条一面:Spring IOC容器中只存放单例Bean吗?
最近,很多小伙伴出去面试,感觉自己面的不是很理想,回来后,不少小伙伴把面试题做了记录发给我,让我给大家解析下,然后发出来。当我看到这些面试题时,快速在脑海中构建起了整个知识体系,从基础到框架、从分布式到微服务,从数据结构到算法,从虚拟化到云原生,从大数据到云计算,从实战项目到性能调优。其实,这些面试本质上不难,很多都是对于基础知识的考察。
今天开始,我们就来一一突破这些大厂的面试题,好了,开始今天的正文。
问题:
正如题目所说:Spring IOC容器中只存放单例Bean吗?
先给出结论吧
这里,想来想去,我还是直接了当的说吧:是的,Spring IOC容器中只存放单例Bean。接下来,且听我细细道来为哈只存放单例Bean。
问题分析
既然,我们已经知道Spring IOC容器中只存放单例Bean,但是在面试的时候不能只说这一句话呀,否则,面试官就会把你直接Pass掉。为啥?如果你只说这一句话,面试官可能就会认为你是懵的,而且懵对的概率为50%,如果你懵错了,面试官认为你不会,如果你懵对了,面试官有可能也会认为你不会。所以,除了答对结论之外,还要清晰的说出Spring IOC容器中为啥只存放单例Bean。
好了,我们正式开始分析这个问题。
IOC容器初始化的时候,会将所有的bean初始化在singletonObjects这个ConcurrentHashMap中, bean是单例的。
在获取bean的时候,首先会从singletonObjects去取,通过debug,发现如果scope是单例,则可以获取到bean,如果scope是多例,则获取不到bean,需要从一个叫mergedBeanDefinitions的ConcurrentHashMap中去获取bean的定义,然后再根据bean的scope去决定如何创建bean,如果scope=prototype,则每次都会创建一个新的实例。
这里,我们可以大概得出这样的结论:
IOC在初始化时,只会将scope= singleton(单例)的对象进行实例化,而不会去实例化scope=prototype的对象(多例)。
接下来,我们就来debug一下Spring的源码。
首先,我们创建一个用于测试作用域为多例,获取不同实例的Person类,如下所示。
public class Person {@Value("张三")private String name;@Value("#{20-2}")private Integer age;@Value("${person.nickName}")private String nickName;public Person() {}public Person(String name, Integer age) {this.name = name;this.age = age;}//省略get/set
}
接下来,创建一个MainConfig类,如下所示。
@Configuration
public class MainConfig {@Bean("person")@Scope("prototype")public Person person(){System.out.println("给容器中添加Person...");return new Person("张三", 25);}
}
可以看到,此时MainConfig测试的是作用域为多例,获取不同实例的场景。而如果要想测试作用域为单例,获取相同实例的场景,则只需要将MainConfig类中的person()方法上的 @Scope("prototype")注解去掉即可,如下所示。
@Configuration
public class MainConfig {@Bean("person")public Person person(){System.out.println("给容器中添加Person...");return new Person("张三", 25);}
}
接下来,再编写一个main方法用于启动测试程序。
public static void main(String[] args){ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);Person person = applicationContext.getBean(Person.class);Person person2 = applicationContext.getBean(Person.class);if(person.equals(person2)){System.out.println("同一个实例");}else{System.out.println("不同的实例");}
}
启动程序,开始debug测试单例情况。
调试单例作用域
经过debug调试,在单例情况下,首次从singletonObjects 这个Map中获取的bean为空,以后每次获取时,从singletonObjects这个Map中获取的bean就不为空了,会直接返回从这个Map中获取的值。
第一次从singletonObjects 中获取值的情况如下所示。
第二次再从singletonObjects这个Map中获取的bean就不为空了。
此时,命令行会打印同一个实例。
说明单例作用域下,每次共用一个bean实例,并且这个bean实例是被保存到容器中的。
调试多例作用域
如果是多例情况,则外界无论获取多少个bean,从singletonObjects 这个Map中都获取不到对应的bean实例,每次都需要新建一个bean返回。
通过调试源码,可以发现,当bean是多例时,每次都会从一个叫做 mergedBeanDefinitions 的HashMap中获取一个RootBeanDefinition对象,里面包含了bean的一些基础信息,如下所示。
接下来,再根据bean的scope属性来做处理,如果作用域是单例,则直接从容器中获取,如果作用域是多例,则每次会创建一个实例。
此时,命令行会打印出不同的实例。
说明多例作用域下,每次都会创建一个bean实例并返回。
综上所述:Spring IOC容器中只存放单例Bean。
头条一面:Spring IOC容器中只存放单例Bean吗?相关推荐
- java 从一个容器获取对象,如何从 Spring IoC 容器中获取对象?
前面几篇文章主要分析了 Spring IoC 容器如何初始化,以及解析和注册我们定义的 bean 信息. 其中,「Spring 中的 IoC 容器」对 Spring 中的容器做了一个概述,「Sprin ...
- Spring IOC 容器源码分析 - 创建原始 bean 对象
1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...
- 【小家Spring】Spring注解驱动开发---向Spring Ioc容器中注册Bean的7种方式
每篇一句 比你有钱的人一定会比你努力,而比你努力的人终有一天会比你有钱 前言 Spring是一个非常强大的反转控制(IOC)框架,以帮助分离项目组件之间的依赖关系.因此可以说Spring容器对Bean ...
- Spring学习--实现 FactoryBean 接口在 Spring IOC 容器中配置 Bean
Spring 中有两种类型的 bean , 一种是普通的 bean , 另一种是工厂 bean , 即 FactroyBean. 工厂 bean 跟普通 bean 不同 , 其返回的对象不是指定类的一 ...
- Spring中将BeanDefinition注册到IOC容器中
Spring中将BeanDefinition注册到IOC容器中 XML配置元信息 <bean name="-" - /> 注解: @Bean,@Component,@I ...
- Spring IOC 容器源码分析 - 循环依赖的解决办法
1. 简介 本文,我们来看一下 Spring 是如何解决循环依赖问题的.在本篇文章中,我会首先向大家介绍一下什么是循环依赖.然后,进入源码分析阶段.为了更好的说明 Spring 解决循环依赖的办法,我 ...
- Spring IOC 容器源码分析 - 获取单例 bean
1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...
- Spring —— IoC 容器详解
引言 本篇博客总结自官网的<The IoC Container>,其中会结合王富强老师的<Spring揭秘>融入自己的语言和理解,争取通过这一篇文章彻底扫除spring IOC ...
- IOC 容器中那些鲜为人知的细节(关于 autowiring)
1.博客内容均出自于咕泡学院架构师第三期 2.架构师系列内容:架构师学习笔记(持续更新) Spring IOC 容器提供了两种管理 Bean 依赖关系的方式: 1).显式管理:通过 BeanDefin ...
最新文章
- PTA数据结构与算法题目集(中文)7-14
- 使用AI画一个冠状病毒
- 算法竞赛入门经典读书笔记(四)7.3子集生成
- 滴滴顺风车上线新功能,特殊时期便捷出行
- Linux IPC之有名管道
- 88. [ExtJS2.1教程-5]ToolBar(工具栏)
- Django项目实践2 - Django模板(view-html)
- 高斯消元法(Gauss Elimination) 分析 题解 模板——czyuan原创
- Quartus 13.0安装教程
- 跑分cpu_跑分完爆骁龙 865?明年这些中端处理器真的要起飞
- 计算机一级二级三级四级相当的水平,计算机等级考试通过必看:一至四级通关策略...
- python 输出后面多一个None
- 基于Element UI Calendar实现日程提醒功能
- 【算法】扩展卢卡斯详解
- 引发卡塔尔断交潮的“俄罗斯黑客”究竟有多牛?
- 太真实,北上广深年薪20W、30W、40W的程序员的生活状态!
- 2018-2019 ACM-ICPC, China Multi-Provincial Collegiate Programming Contest
- 快速搞定Jupyter Notebook添加代码自动补全功能
- 哔哩哔哩直播姬和OBS源码对比
- JavaScript 01 JavaScript 是什么
热门文章
- Podman中如何运行一个 Linux 虚拟机?
- PHP 中 include 和 require 的概要及区别介绍
- C语言如何实现泛型编程?
- 根据开源数据库选择合适的工具
- Oracle导入csv数据字符集,用SQLLDR把.CSV文件导入到数据库时,出现无法定位字符集句柄以用于字符集标识(0)...
- BZOJ 1589 Trick or Treat on the Farm (tarjan缩点,记忆化搜索)[Usaco 2008 Dec Gold]【BZOJ计划】
- gitee 拉取其他分支_如何使用 Gitee 快速搭建 ESP-IDF 开发环境(Windows 版)
- es文件ftp服务器,es文件夹 ftp服务器
- python与c语言数据交互,python与c语言交互应用实例
- 数据泄露频繁,背后原因之--数据的利益