> 文档中心 > 《几乎必问》Spring 面试题开胃菜

《几乎必问》Spring 面试题开胃菜

继上一篇 Spring 循环依赖的面试题之后,我又来啦。

这篇汇总几个Spring 面试时候的开胃菜,也就是提问起手式。

话不多少,发车!

说下你理解的 Spring

可以从两个层面来理解 Spring。

第一个层面指的是 Spring Framework,是一个开源的应用框架,提供 IOC 和 AOP 降低了应用开发的复杂度。

第二个层面指的是 Spring 全家桶,Spring 发展到今天可以说几乎是统领了 Java,有关 Java 应用开发所需的全部功能, Spring 都提供了解决方案。

包括对批处理的支持、对 web 的支持、对微服务的支持等。

这种题大致说一下就行了,不需要太多细节,面试官会接着追问的。

看过源码吗?说下 Spring 由哪些重要的模块组成?

Spring 最主要的核心就是一个容器,这个容器根据我们的配置文件创建了各种 Bean 且编织它们之间的依赖关系,管理这些 Bean 的生命周期。

所以最核心的代码模块是:

  • spring-core:核心类库,包括资源访问等一些工具类,别的模块都会依赖此模块

  • spring-beans:对 Bean 的支持,包括控制反转和依赖注入,核心工厂 BeanFacotry 就在这个模块。

  • spring-context:Spring 的上下文,支持数据验证、国际化、事件传播等支持,ApplicationContext 就在这里,可以理解为运行时的 Spring 容器。

基于上面的这些核心模块,Spring 也提供了很多重要的支持:

  • spring-aop:AOP 的支持

  • spring-jdbc:jdbc 的支持

  • spring-orm: orm 的支持

  • spring-webmvc: mvc 的支持

  • 等等

什么是 IOC?

IOC,即Inversion of Control,控制反转。

首先要明确 IOC 是一种思想,而不是一个具体的技术,其次 IOC 这个思想也不是 Spring 创造的。

然后我们要理解到底 控制 的是什么,其实就是 控制对象的创建 ,IOC 容器根据配置文件来创建对象,在对象的生命周期内,在不同时期根据不同配置进行对象的创建改造。

那什么被 反转 了?

其实就是关于创建对象且注入依赖对象的这个动作,本来这个动作是由我们程序员在代码里面指定的。

例如对象 A 依赖对象 B,在创建对象 A 代码里,我们需要写好如何创建对象 B,这样才能构造出一个完整的 A。

而反转之后,这个动作就由 IOC 容器触发,IOC 容器在创建对象 A 的时候,发现依赖对象 B ,根据配置文件,它会创建 B,并将对象 B 注入 A 中。

这里要注意,注入的不一定非得是一个对象,也可以注入配置文件里面的一个值给对象 A 等等。

至此,你应该明确了,控制和反转。

IOC 有什么好处?

对象的创建都由 IOC 容器来控制之后,对象之间就不会有很明确的依赖关系,使得非常容易设计出松耦合的程序。

例如,对象 A 需要依赖一个实现,但是对象都由 IOC 控制之后,我们不需要明确地在对象 A 的代码里写死依赖的实现。

例如只需要写明依赖一个接口,这样我们的代码就能顺序的编写下去。

然后,我们可以在配置文件里定义 A 依赖的具体的实现(比如 B),根据配置文件,在创建 A 的时候,IOC 容器就知晓 A 依赖的 B,这个注入这个依赖即可。

如果之后你有新的实现需要替换,那 A 的代码不需要任何改动,你只需要将配置文件 A 依赖 B 改成 B1,这样重启之后,IOC 容器会为 A 注入 B1。

这样就使得类 A 和类 B 解耦了, very nice!

并且也因为创建对象由 IOC 全权把控,那么我们就能很方便的让 IOC 基于扩展点来“加工”对象。

例如我们要代理一个对象,IOC 在对象创建完毕,直接判断下这个对象是否需要代理,如果要代理,则直接包装返回代理对象。

这等于我们只要告诉 IOC 我们要什么,IOC 就能基于我们提供的配置文件,创建符合我们需求的对象。

正是这个控制反转的思想,解放了我们的双手 。

什么是 DI

DI,Dependency Injection,依赖注入。

普遍的答案是 DI 是 IOC 的一种实现。

其实它跟 IOC 的概念一致,只是从不同角度来描述罢了。

Martin Fowler 提出了 DI 的概念,它觉得用 DI 来形容更加具体。

大致理解为容器在运行的时候,可以找到被依赖的对象,然后将其注入,通过这样的方式,使得各对象之间的关系可由运行期决定,而不用在编码时候明确。

什么是 Bean

可以认为,由 Spring 创建的、用于依赖注入的对象,就是 Bean。

例如调用 getBean 能返回的玩意,就是 Bean。

最后

最近比较忙,先理了这几道开胃菜,不过虽说是开胃菜,但是充分理解上面的答案对于理解 Spring 的核心思想非常关键。

毕竟真要抽象来讲,Spring 也就是个 IOC 容器,也正是因为由它来管理 Bean 的生命周期,所以能特意在不同生命周期设计出很多扩展点让程序员定制化。

我们只要实现那些扩展点,就能对 Bean 做改造,所以一个属性值的替换、AOP 等就非常容易实现。