写点什么

遇到或问过的一些 Spring 面试题(持续更新)

作者:Lazy
  • 2021 年 12 月 22 日
  • 本文字数:1451 字

    阅读完需:约 5 分钟

问题 1: Spring 为什么建议使用构造器注入而不是加 @Autowired 或者 @Resource 属性注入


答:之所以不推荐属性注入,主要是有以下几个缺点:

  1. 如果使用属性注入,经常能看到一个类里有 6-7 甚至十几个 service,repository 被引入,因为这种写法简单,往往忽略了某些业务是否真的合适放到这个类中来处理,也就是容易破坏单一职责原则。如果通过构造器的话,当发现参数过多时(代码异味),更容易引起思考。

  2. 与容器紧耦合了,依赖容器进行初始化,比如在单元测试的时候必须启动容器,比较麻烦,效率也不高,而且你的类不能在容器外使用,简单说就是依赖注入框架的核心思想之一就是受容器管理的类不应该去依赖容器所使用的依赖。

  3. 无法及时暴露空指针异常,Spring 团队提倡使用基于构造方法的注入,将依赖注入到一个不可变的变量中(final 修饰),保证这个值不会为 null。


问题 2:概述 Spring 处理 HTTP 请求的流程和机制


答: 这是一个开放性问题,考察对 Spring 框架的理解深度,要答好这个问题可以参考以下思路:

(1) 简述 http 请求的处理的过程:一个请求经过流量防火墙、网关等最终到达 WEB 容器,比如 SpringBoot 内嵌支持的 Tomcat/Jetty/Undertow, 容器会将请求交给 WEB 应用处理并最终返回给客户端;

(2) 理解 WEB 应用的三个核心组件: Filter、Listener、Servlet

  • Filter: 负责对 HTTP 请求的预处理和响应的后处理,Spring 体系提供了不少 Filter,spring-security 利用 filter 实现认证。

  • Listener:主要用于监听 Application、Session、Request 等对象的变化,每当这些对象发生变化就会回调用对应的监听方法。Spring 暂时还不清楚有哪些组件用到 Listener 比较多的,但是如果真有需求需要监听 Request 变化,可以实现一个 ServletRequestListener,使用 @WebListener 注解类。

  • Servlet: 负责接收请求,处理请求,反馈响应结果,实际上请求在经过一系列 Filter 之后就会进入到 spring-web 的 DispatcherServlet 中进行分发处理。

(3) 理解 spring-web 的核心组件:Controller、HandlerMapping、HandlerAdapter、Service、Repository

  • Controller: 控制器,负责调度

  • HandlerMapping: 主要负责控制器 Controller 的注册和查找,使用 map 实现,其中 key 是 URI 信息,value 是 spring bean 的名称或者 HandlerExecutionChain,这个 chain 里持有了所有注册的 Spring 拦截器 HandlerInterceptor

  • Service: 负责实现具体的业务逻辑

  • Repository: 也就是 DAO, 访问数据

处理请求的过程大致如下:

  1. 请求到达 DispatcherServlet 后,首先根据 URI 信息获取 HandlerExcutionChain

  2. 接着 DispatcherServlet 会调用 HandlerExcutionChain 的 getHandler(Request)方法获取 Handler,并为这个 Handler 找到对应的 HandlerAdapter, 但 DispatcherServlet 并不会直接就执行 Adapter 的 handle 方法(实际就是调用 controller 方法)

  3. DispatcherServlet 会先执行 HandlerExcutionChain applyPreHandle 方法,这个方法会循环遍历所有 Spring 拦截器,执行拦截器的 preHandle。

  4. DispatcherServlet 执行 HandlerAdapter 的 handle 方法,进而调用 controller 对应的方法,在调用前会使用 argumentResolvers 来处理请求参数,调用后会 returnValueHandlers 对结果进行处理,平时使用的 MessageConverter 就是在这些 returnValueHandlers 中调用的,具体可以跟下 ServletInvocableHandlerMethod 的源码查看。

  5. 同样在执行完 Adapter 的 handle 方法后会调用 HandlerExcutionChain applyPostHandle 方法,循环执行拦截器的 postHandle。

  6. 最后 DispatcherServlet 会对结果进行 View 渲染,结束时调用 HandlerExcutionChain 的 triggerAfterCompletion,循环执行拦截器的 afterCompletion 方法;


发布于: 2021 年 12 月 22 日
用户头像

Lazy

关注

某知名软件上市公司基层软件开发。 2019.10.17 加入

助力于脑科学软件工程,为中国脑计划舔砖加瓦。 脑科学软件工程包含多种模态数据的处理分析(如脑影像、基因、行为评测等)、脑相关科研平台、研究成果转化。其应用可覆盖到医疗、教育、生活娱乐等各个领域。

评论

发布
暂无评论
遇到或问过的一些Spring面试题(持续更新)