《几乎必问》Spring 面试题开胃菜
共 2061字,需浏览 5分钟
·
2022-06-21 12:56
说下你理解的 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 等就非常容易实现。