Spring Boot启动了几个IoC容器?如何证明?

开发 前端
如果Spring家族没有推出Spring Boot,Spring是有被取代风险的,因为那时的开发者对它的配置繁琐、使用曲线较高已有所反感(即使比EJB还轻太多)。

你好,我是YourBatman:当我老了,也写代码;不为别的,只为爱好。

📚前言

不少面试者说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容器,这不正是我们想要证明的事嘛

@Service
public class DemoService implements ApplicationContextAware {

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(getClass().getSimpleName() + "所属IoC容器的地址值:"
+ ("@" + Integer.toHexString(applicationContext.hashCode())));
}

}

启动Spring Boot,控制台输出:

DemoConfiguration所属IoC容器的地址值:@4b2bac3f
DemoController所属IoC容器的地址值:@4b2bac3f
DemoService所属IoC容器的地址值:@4b2bac3f

地址值一模一样。因此可得出结论:这些Bean都来自同一个IoC容器,从而“间接”证明了Spring Boot只启动一个IoC容器。

扩展:从结果上证明的其它方式

从结果上证明,笔者上面举例的方式是最推荐的方式。但毕竟表现方式可以有多种,这里再做简单例举:

★通过依赖注入方式注入ApplicationContext进行比较,就像这样:

@Service
public class DemoService implements ApplicationContextAware {

@Autowired
private ApplicationContext applicationContext;

}

理论依据:若只有一个IoC容器,任何地方注入的ApplicationContext都应该是同一个。

★★通过Bean之间互相依赖注入,看是否能正常启动,就像这样:

@RestController
public class DemoController implements ApplicationContextAware {
@Autowired
private DemoService demoService;
}

@Service
public class DemoService implements ApplicationContextAware {
@Autowired
private DemoController demoController;
}

理论依据:不同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只是将它留给了自己,这不正是优秀框架该有的样子嘛

责任编辑:武晓燕 来源: YourBatman
相关推荐

2009-06-22 10:20:01

Spring IoC容

2023-09-27 08:14:56

2023-06-02 16:24:46

SpringBootSSM

2023-04-28 08:43:46

2019-07-15 10:00:53

DockerJava容器

2019-07-15 16:00:24

Docker架构容器

2017-03-06 15:43:33

Springboot启动

2023-10-25 18:08:13

应用容器化Docker

2020-08-06 00:14:16

Spring IoC依赖注入开发

2020-07-14 11:00:12

Spring BootRedisJava

2021-08-06 08:04:14

Spring Boot自动配置

2015-10-09 11:02:02

2021-04-29 07:18:21

Spring IOC容器单例

2023-10-15 22:40:25

插件JIB

2017-12-25 13:51:32

LinuxUbuntu LinuLXD容器

2012-02-02 13:04:50

JavaSpring

2022-12-07 08:02:43

Spring流程IOC

2020-07-03 08:00:11

Spring BootSpring Clou流程

2017-03-23 09:29:06

2020-09-02 17:28:26

Spring Boot Redis集成
点赞
收藏

51CTO技术栈公众号