📚前言
不少面试者说Spring Boot和传统Spring/Spring MVC一样,对又不对。比如IoC容器Spring Boot只用一个,而传统的Spring MVC一般都是2个;比如Spring Boot不建议你使用@EnableWebMvc注解,而这在传统Spring MVC项目里几乎是必须的。
2017年之后,Spring Boot以不可挡之势在国内逐渐成为主流,本文这个问题就基于Spring Boot环境的。
✍正文
Ioc,即“控制反转”,它不是一种技术,而是一种设计思想。Spring框架对此提供了完整实现,并早已成为事实标准。
IoC的实现框架不只有Spring,比较著名还有Google的的Guice
理解IoC容器,是进阶Spring Boot源码的基础中的基础,那就先从这个问题开始吧:Spring Boot启动了几个IoC容器?如何证明?
启动了几个IoC容器?
1个
Tips:在传统Spring MVC环境,这个答案是1或者2;在Spring Cloud环境,答案可以是1、2、3、4...都有可能
如何证明?
如何证明才是本问题的核心嘛,否则即使上面个数答对了也会被认为是蒙的。
大部分问题都可以从两个方向上来给出证明,这就像证明某个物理/化学现象时,可以通过实验结果证明,另外也可以从书本的理论(在编程领域也就是源代码)上“证明”。
从结果上证明
我准备了一个典型的 Spring Boot项目:
为了验证这些这些Bean都来自同一个IoC容器,这里用到了ApplicationContextAware接口,就像这样:
实现了接口ApplicationContextAware的Bean,IoC容器会在初始化此Bean时回调setApplicationContext方法,将自己“传进去”。换句话讲:哪个IoC容器初始化了此Bean就传入哪个IoC容器,这不正是我们想要证明的事嘛
启动Spring Boot,控制台输出:
地址值一模一样。因此可得出结论:这些Bean都来自同一个IoC容器,从而“间接”证明了Spring Boot只启动一个IoC容器。
扩展:从结果上证明的其它方式
从结果上证明,笔者上面举例的方式是最推荐的方式。但毕竟表现方式可以有多种,这里再做简单例举:
★通过依赖注入方式注入ApplicationContext进行比较,就像这样:
理论依据:若只有一个IoC容器,任何地方注入的ApplicationContext都应该是同一个。
★★通过Bean之间互相依赖注入,看是否能正常启动,就像这样:
理论依据:不同IoC容器之间的Bean是隔离,不能互相注入。
父子容器:子容器可以注入父容器的Bean,反之不行
从源码上“证明”
Spring Boot启动过程核心,源代码都在SpringApplication#run这里:
步骤的具体详情就不展开了,太枯燥了。有兴趣的可看我之前文章的源码解析,也可看别人的或者B站的。
总之,在应用中的Spring,IoC容器要想“启动”都会调用refresh()方法,而Spring Boot有且仅会调用1次这个方法,所以可证明:Spring Boot有且只启动了1个IoC容器。
🍞总结
如果Spring家族没有推出Spring Boot,Spring是有被取代风险的,因为那时的开发者对它的配置繁琐、使用曲线较高已有所反感(即使比EJB还轻太多)。
Spring Boot横空出世的宗旨就一个:让一切变得简单,一个框架、一个入口、一个IoC容器(摒弃复杂的父子容器概念),大大降低了使用复杂度。迅速普及,从而巩固了Spring的霸主地位,不可撼动。
复杂度不可能凭空消失,Spring Boot只是将它留给了自己,这不正是优秀框架该有的样子嘛