最近,很多小伙伴出去面试,感觉自己面的不是很理想,回来后,不少小伙伴把面试题做了记录发给我,让我给大家解析下,然后发出来。当我看到这些面试题时,快速在脑海中构建起了整个知识体系,从基础到框架、从分布式到微服务,从数据结构到算法,从虚拟化到云原生,从大数据到云计算,从实战项目到性能调优。其实,这些面试本质上不难,很多都是对于基础知识的考察。

今天开始,我们就来一一突破这些大厂的面试题,好了,开始今天的正文。

问题:

正如题目所说: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吗?相关推荐

  1. java 从一个容器获取对象,如何从 Spring IoC 容器中获取对象?

    前面几篇文章主要分析了 Spring IoC 容器如何初始化,以及解析和注册我们定义的 bean 信息. 其中,「Spring 中的 IoC 容器」对 Spring 中的容器做了一个概述,「Sprin ...

  2. Spring IOC 容器源码分析 - 创建原始 bean 对象

    1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...

  3. 【小家Spring】Spring注解驱动开发---向Spring Ioc容器中注册Bean的7种方式

    每篇一句 比你有钱的人一定会比你努力,而比你努力的人终有一天会比你有钱 前言 Spring是一个非常强大的反转控制(IOC)框架,以帮助分离项目组件之间的依赖关系.因此可以说Spring容器对Bean ...

  4. Spring学习--实现 FactoryBean 接口在 Spring IOC 容器中配置 Bean

    Spring 中有两种类型的 bean , 一种是普通的 bean , 另一种是工厂 bean , 即 FactroyBean. 工厂 bean 跟普通 bean 不同 , 其返回的对象不是指定类的一 ...

  5. Spring中将BeanDefinition注册到IOC容器中

    Spring中将BeanDefinition注册到IOC容器中 XML配置元信息 <bean name="-" - /> 注解: @Bean,@Component,@I ...

  6. Spring IOC 容器源码分析 - 循环依赖的解决办法

    1. 简介 本文,我们来看一下 Spring 是如何解决循环依赖问题的.在本篇文章中,我会首先向大家介绍一下什么是循环依赖.然后,进入源码分析阶段.为了更好的说明 Spring 解决循环依赖的办法,我 ...

  7. Spring IOC 容器源码分析 - 获取单例 bean

    1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...

  8. Spring —— IoC 容器详解

    引言 本篇博客总结自官网的<The IoC Container>,其中会结合王富强老师的<Spring揭秘>融入自己的语言和理解,争取通过这一篇文章彻底扫除spring IOC ...

  9. IOC 容器中那些鲜为人知的细节(关于 autowiring)

    1.博客内容均出自于咕泡学院架构师第三期 2.架构师系列内容:架构师学习笔记(持续更新) Spring IOC 容器提供了两种管理 Bean 依赖关系的方式: 1).显式管理:通过 BeanDefin ...

最新文章

  1. PTA数据结构与算法题目集(中文)7-14
  2. 使用AI画一个冠状病毒
  3. 算法竞赛入门经典读书笔记(四)7.3子集生成
  4. 滴滴顺风车上线新功能,特殊时期便捷出行
  5. Linux IPC之有名管道
  6. 88. [ExtJS2.1教程-5]ToolBar(工具栏)
  7. Django项目实践2 - Django模板(view-html)
  8. 高斯消元法(Gauss Elimination) 分析 题解 模板——czyuan原创
  9. Quartus 13.0安装教程
  10. 跑分cpu_跑分完爆骁龙 865?明年这些中端处理器真的要起飞
  11. 计算机一级二级三级四级相当的水平,计算机等级考试通过必看:一至四级通关策略...
  12. python 输出后面多一个None
  13. 基于Element UI Calendar实现日程提醒功能
  14. 【算法】扩展卢卡斯详解
  15. 引发卡塔尔断交潮的“俄罗斯黑客”究竟有多牛?
  16. 太真实,北上广深年薪20W、30W、40W的程序员的生活状态!
  17. 2018-2019 ACM-ICPC, China Multi-Provincial Collegiate Programming Contest
  18. 快速搞定Jupyter Notebook添加代码自动补全功能
  19. 哔哩哔哩直播姬和OBS源码对比
  20. JavaScript 01 JavaScript 是什么

热门文章

  1. Podman中如何运行一个 Linux 虚拟机?
  2. PHP 中 include 和 require 的概要及区别介绍
  3. C语言如何实现泛型编程?
  4. 根据开源数据库选择合适的工具
  5. Oracle导入csv数据字符集,用SQLLDR把.CSV文件导入到数据库时,出现无法定位字符集句柄以用于字符集标识(0)...
  6. BZOJ 1589 Trick or Treat on the Farm (tarjan缩点,记忆化搜索)[Usaco 2008 Dec Gold]【BZOJ计划】
  7. gitee 拉取其他分支_如何使用 Gitee 快速搭建 ESP-IDF 开发环境(Windows 版)
  8. es文件ftp服务器,es文件夹 ftp服务器
  9. python与c语言数据交互,python与c语言交互应用实例
  10. 数据泄露频繁,背后原因之--数据的利益