【原创】008 | SpringBoot 源码专车总结(共8篇)
20大进阶架构专题每日送达
1.前言
xxx 专车?不知道大家的脑海里是否会立马浮现出一种似曾相识,却又无法记起的回忆?是的,你没想错,这就是你曾经热爱的 SpringBoot 源码分析专车系列。曾几何时,作者不断的更新文章,自己又不断地从文章中汲取知识,而如今随着时间的流逝,该放的也都放下了,该忘的一点也不敢留下。
不,这不是作者想要的结果,也不是你想要的结果,只怪岁月蹉跎了你,让你的记忆曲线不断下滑。通过此篇文章我将帮助你提升你的记忆曲线,一起回到那个快乐学习的时代。
2.系列回顾
接下来让我带着你回顾一下 SpringBoot 源码分析专车系列的文章
通过如上的列举,应该能够让你回忆起些点滴轮廓,有一个大概的认识。当然,这远远达不到我写此篇文章的要求,我所要做的就是让你拾起你的记忆,巩固你的知识,重新燃起学习的激情。接下来我会通过问答方式来加深下你的理解。
2.1 SpringBoot 自动注入源码分析
刚开始工作的时候,使用的是 Spring、Spring MVC 框架,项目结构也采用的是三层模型。如你所知,三层模型有控制器、业务层、数据库交互层,在控制器层,我们会声明业务层引用属性,然后通过@Autowired 注解来注入我们需要的对象,然后通过该属性.方法名来调用业务层方法,从而实现我们的业务逻辑?
随着工作年限的增加,突然有一天就很好奇,这种注入是在什么时候注入进来的,又是如何实现的?如果同一类型的对象有多个,是如何选择我们想要的对象的?下面就一一解答这些曾经困扰我的疑惑,我想这也可能是你的疑惑。
2.1.1 注入是在什么时候注入进来的以及如何实现?
请你回忆下,平时是如何如何给对象属性赋值的?你肯定会 new 一个对象,然后调用 set 方法来赋值,其实框架里面注入也值通过该思路实现的。
这三张图符合上面我给你讲到的思路,第一步实例化我们的 bean 对象,第二步执行 populateBean,就是填充 bean(上面提到的调用 set),只是框架更牛叉,它将这种填充能力交给 bean 处理器来实现,也就是第三步遍历处理器,找到 AutowiredAnnotationBeanPostProcessor 这个 bean 处理器来提供注入能力。到这里我相信你应该比我更了解注入的原理。
2.2.2 多种同类型实例存在,是如何注入的?
不知你是否还记得,我在源码分析章节中讲了一个示例,示例中定义了一个 PersonService 接口,有 StudentService、TeacherService 两个接口实现类。你大概也从其它博客中了解过@Autowired 注解是通过类型进行注入的,那么如果注入 StudentService,肯定会报错,实际上却可以成功注入。来看看实际情况:
事实深刻的告诉我们,当存在多个匹配的 bean 的场景下,会通过@Primary 注解、优先级、名称来选择合适的 bean。到这里,我可以肯定自动注入原理已经深深刻在了你的脑海里。
2.2 SpringBoot 事务源码分析
事务是我们开发过程中必不可少的知识点,了解事务原理,至少你可以轻松掌握 AOP 知识点,可以通过模仿事务原理来实现记录系统请求日志功能。
正如你所了解的,AOP 三个核心概念:切面、切点、通知。下面我会带着你领略框架是如何依照核心来实现事务的。
看到这里,我认为你应该会有种恍然大悟的感觉,为什么使用事务要使用@Transactional 注解?因为这个注解要被当做切点来切入。
在配置类中也声明了通知,也就是当我们切中"要害"后,如何进行下一步。
其实事务相关知识点远远不止这么多。比如:
-
多线程环境执行事务,为什么出现数据不安全? -
为什么在非事务方法中通过 this 调用调用事务注解的方式,事务会不生效? -
事务提供的钩子函数 afterCommit()执行的时候,数据库连接是否释放了?
我希望你对事务的了解不仅仅如此,由于篇幅问题,就不在此一一赘述了,相信你会掌握的比我更好,加油!
2.3 SpringBoot 请求源码分析
我猜你曾经有过这样的困扰:
-
请求参数无法注入到方法参数上 -
响应结果不是自己想要的 json 数据,却返回了页面
我自己曾经也困惑,web 请求处理是如何实现的?为什么我定义个@RequestMapping 就可以执行我的方法?
后来看了源码之后才解开了我的疑惑,原来框架将映射路径和我们的方法进行绑定,当请求应用的时候,从绑定关系中找到我们的业务方法,执行业务方法流程就跑起来了。
下面会来解答你遇到的困惑:
正如你所见到的,框架为我们设置了许多的参数解析器,例如 RequestResponseBodyMethodProcessor 用来解析请求参数,并将参数映射到我们的方法参数上。再来看看该解析器支持参数形式
你应该一下就明白了,当我们以 application/json 形式请求接口,需要使用@RuqestBody 注解来修饰方法参数。
再来看看返回值处理器
很巧,可以看到返回值处理器中也有 RequestResponseBodyMethodProcessor
该返回值处理器支持的返回类型就是要在类上或者方法上加上@ResponseBody 注解,这也就是写 rest 接口为什么要使用@RestController 标注,再来看看@RestController 的定义
到此使用@RequestBody 注解和@RestController 注解的真相也就浮出水面了
2.4 SpringBoot 拦截器原理
拦截器实现原理很简单,下面先看几张图,你大概就知道了
首先注入了 WebMvcConfigurer 接口集合,然后遍历 WebMvcConfigurer 集合,调用实现类的 addInterceptors 方法,来添加拦截器。
到此,你就明白,当自定义拦截器时,需要实现 WebMvcConfigurer 接口并重写 addInterceptors,在 addInterceptors 方法中添加我们自定义的拦截器实例的原理了。
3.总结
这篇文章算是对之前的系列文章做一个总结,针对已经忘记的你,希望能帮你快速拾起记忆;针对还不了解原理的你,希望在此之后可以让你恍然大悟,在今后的编程中更加的自信。
在今后我也会继续给大家分享我的知识点,愿你我能一起努力,共同进步。
4.感悟
其实学习技术是一条漫长的路,只有一步一个脚印,踏踏实实啃好每部分知识点,将知识串成体系,让技术掌握牢固,会让自己在学习一些所谓的高阶技术的时候,会轻松许多。
编程之路,路漫漫其修远兮,吾将上下而求索。
———— e n d ————
快年底了,师长为大家准备了三份面试宝典:
《java面试宝典5.0》(对标8-13K)
《350道Java面试题:整理自100+公司》(对标12-20K)
《资深java面试宝典-视频版》(对标20K+)
分别适用于初中级,中高级,以及资深级工程师的面试复习。
内容包含java基础、javaweb、各个性能优化、JVM、锁、高并发、反射、Spring原理、微服务、Zookeeper、数据库、数据结构、限流熔断降级等等。
获取方式:点“在看”,扫码关注师长的小号:编程最前线并回复 面试 领取,更多精彩陆续奉上。