【框架】Spring 框架重点解析
Spring 框架重点解析
1. Spring 框架中的单例 bean 是线程安全的吗?

不是线程安全的
- Spring 框架中有一个 @Scope 注解,默认的值是 singleton,即单例的;
- 因为一般在 Spring 的 bean 对象都是无状态的(在生命周期中不被修改的,比如正经开发下, service 层的和 dao 层的),没有线程安全问题;
- 如果在 bean 中定义了可修改的成员变量,是要考虑线程安全问题的,可以使用多例 prototype 或者加锁来解决;
2. 什么是 AOP,你们项目中有没有使用到 AOP 呢?

什么是 AOP ?
- 面向切面编程,用户将与业务无直接相关,但却对多个对象产生影响的公共行为和逻辑,将这些抽取成公共模块进行复用,降低耦合度;
- 可以理解为 一组业务的效果上的"增强buff" ;
原理就是动态代理
- 即目标方法的执行时机和结果可以由代理决定和处理;
你们项目有没有使用到 AOP ?
- 如 统一处理(拦截器、异常处理器、响应处理器),记录接口访问日志,缓存处理,Spring 实现的事务;
- 记录接口访问日志核心就是,使用 Spring AOP 中的环绕通知 + 切点表达式(找到记录日志的方法),通过环绕通知的参数获取请求方法的参数,获得这些参数后,进行一些业务;
joinPoint.proceed();
代表,切入点执行,也就是目标方法的执行;
3. Spring 中的事务是如何实现的?
对于编程式事务,事务的维护还是有目标方法的业务进行,没用到 AOP,对业务代码入侵性大,项目中很少使用;
而对于声明式事务,通过对方法加注解 @Transactional 声明该方法是一个事务
- 其本质是通过 AOP 功能,对方法前后进行拦截,在执行方法之前开启事务,在执行完目标方法之后进行提交或者捕获到异常进行回滚事务;

4. Spring 中事务失效的场景有哪些?
- 异常捕获处理,自己业务中处理了异常,没有抛出,这就意味着这个业务被 Spring 认为是“没有问题,无需回滚”
- 解决:根据实际业务决定是否要手动抛出、手动回滚;
- 抛出检查异常(throws),Spring 默认认为事务抛出的检查异常要被调用者处理,故没有回滚;
- 解决:设置注解 @Transactional 的 rollbackFor 属性为 Exception.class,则即使是检查异常,也会回滚;
- 非 public 方法导致的事务失效,由于 Spring 声明式事务的原理是 Spring AOP,所以创建代理、获取参数、添加事务通知,都要求方法是 public;
- 解决:改为 public;
5. Spring 中 Bean 的生命周期(如何去管理和创建 Bean 实例的?)

推荐文章:【JavaEE】深入了解Spring中Bean的可见范围(作用域)以及前世今生(生命周期)_bean的全局变量-CSDN博客
-
通过 BeanDefinition 获取 Bean 的定义信息,调用构造方法创建 Bean(空);

-
Bean 对象中成员变量的依赖注入;
-
处理 Aware 接口(Bean Name Aware、Bean Factory Aware、ApplicationContextAware);
-
Bean 处理器 BeanPostProcessor - 前置;
-
初始化方法(InitializingBean、init-method);
-
Bean 处理器 BeanPostProcessor - 后置;
- 可以去加强 Bean 对象,例如使其成为代理对象,可以被动态代理;

-
销毁 Bean;
6. Spring 中的循环引用(循环依赖)
6.1 循环依赖是什么?

6.2 Spring 的三种缓存

6.3 一级缓存 + 二级缓存解决普通 Bean 对象的循环依赖
显然,循环依赖的主要原因就是两个对象都是半成品,所以单凭一级缓存是无法解决循环依赖问题的;

6.4 三种缓存一起解决加强 Bean 对象的循环依赖
由于原始对象是没有被特殊处理的,所以只凭借一二级缓存无法注入一些加强对象,如代理对象;
- 因为在 6.3 中,将半成品注入给 B,是因为地址后面不会变化,这样即使注入了半成品,也不会影响结果;
- 而代理对象地址和性质跟原对象是不同的;
这个时候可以加上三级缓存来解决问题;

6.5 构造方法出现了循环依赖
由于 Bean 的生命周期中构造函数是第一个执行的,Spring 框架并不能解决构造器函数的依赖注入,而我们可以通过“延迟加载”来解决问题;

6.6 回答
- 循环依赖:循环依赖也就是循环引用,也就是一个或一个以上的 Bean 互相注入的现象,形成了闭环。如 A 依赖 B,B 依赖 A;
- 循环依赖在 Spring 中是允许存在的,Spring 框架依据三级缓存已经解决了大部分的循环依赖;
- 一级缓存:单例池,存放完整的 Bean 对象;
- 二级缓存:缓存 Bean 半成品对象;
- 三级缓存:缓存的是 ObjectFactory,表示对象工厂,用来创建某个 Bean(间接存储 Bean 对象);
- 当然,Spring 无法解决构造方法出现了循环依赖的问题,但是我们可以通过 @Lazy 注解让某个 Bean “延迟加载”来解决问题;
7. Spring MVC 的执行流程知道吗?
7.1 JSP

7.2 前后端分离

AOP 也大概在 3、4、5 起代理作用,感兴趣可以去研究,不作为重点;
7.3 回答
Spring MVC 的执行流程是这个框架最核心的内容了,有两种:
- 比较老旧的 JSP;
- 比较主流的前后端分离的异步、接口开发;
对于 JSP :
- 用户发送请求到 前端控制器 DispatcherServlet;
- 前端控制器 DispatcherServlet 收到请求调用 处理器映射器 HandlerMapping;
- 处理器映射器 HandlerMapping 将 url 映射到对应的处理器,生成 处理器执行链 HandlerExecutionChain 返回给 前端控制器 DispatcherServlet;
- 前端控制器 DispatcherServlet 调用 处理器适配器 HandlerAdapter;
- 处理器适配器 HandlerAdapter 经过适配调用具体的处理器(Handler/Controller),进行目标方法的参数处理以及返回值处理,并将结果转化为逻辑视图数据 ModelAndView 返回给 前端控制器 DispatcherServlet;
- 前端控制器 DispatcherServlet 将 ModelAndView 传给 视图解析器 ViewReslover;
- 视图解析器 ViewReslover 将 ModelAndView 解析成真实的视图数据 View 返回给 前端控制器 DispatcherServlet;
- 前端控制器 DispatcherServlet 根据 View 进行渲染视图;
- 前端控制器 DispatcherServlet 将页面响应给用户;
对于前后端分离:
- 用户发送请求到 前端控制器 DispatcherServlet;
- 前端控制器 DispatcherServlet 收到请求调用 处理器映射器 HandlerMapping;
- 处理器映射器 HandlerMapping 将 url 映射到对应的处理器,生成 处理器执行链 HandlerExecutionChain 返回给 前端控制器 DispatcherServlet;
- 前端控制器 DispatcherServlet 调用 处理器适配器 HandlerAdapter;
- 处理器适配器 HandlerAdapter 经过适配调用具体的处理器(Handler/Controller),进行目标方法的参数处理以及返回值处理,将数据直接响应给用户;
- 方法上如果添加了 @ResponseBody,处理器适配器 HandlerAdapter 将目标方法的返回值转化为 JSON 字符串再响应给用户;
8. Spring Boot 自动配置原理
我们知道,Spring 中有不少的 Bean 是自带的和程序员自己写的,那么我们通过启动类,是怎么让这些 Bean 自动配置的呢?
就需要理解一下 Spring Boot 自动配置原理
8.1 @SpringBootApplication 注解
- @SpringBootConfiguration:声明一个配置类;
- @ComponentScan:组件扫描,扫描的包路径下的 Bean 存到 Spring 容器中;
- @EnableAutoConfiguration:Spring Boot 实现自动化配置的核心注解;

8.2 @EnableAutoConfiguration 注解
- @Import 注解导入了配置选择器,读取该项目的以及引用的 jar 包的包路径下的 META-INF/spring.factories 文件中的所有配置类;
- 根据一些条件判断的注解去判断是否把配置类中的 Bean 放入 Spring 容器;


8.3 回答

- 在 Spring Boot 项目中的引导类有一个注解 @SpringBootApplication,这个注解其实是对三个注解进行了封装,分别是:
- @SpringBootConfiguration:声明一个配置类;
- @ComponentScan:组件扫描,扫描的包路径下的 Bean 存到 Spring 容器中;
- @EnableAutoConfiguration:Spring Boot 实现自动化配置的核心注解;
- 其中,核心注解 @EnableAutoConfiguration,通过 @Import 注解导入了配置选择器,读取该项目的以及引用的 jar 包的包路径下的 META-INF/spring.factories 文件中的所有配置类;
- 会有一些条件判断的注解(@Conditional 开头),例如:
- @ConditionalOnClass 判断是否有对应的字节码文件,如果有字节码,就加载该类把这个配置类所有的 Bean 放入 Spring 容器中;
- @ConditionalOnMissingBean 加在 @Bean 标注的方法上,判断是否有对应的 Bean,如果对应的 Bean 不存在,则将这个 Bean 放入 Spring 容器;
9. Spring、Spring Boot、Spring MVC 常见注解有哪些?
9.1 Spring 的常见注解有哪些?

9.2 Spring MVC 的常见注解有哪些?

9.3 Spring Boot 的常见注解有哪些?

相关文章:
【框架】Spring 框架重点解析
Spring 框架重点解析 1. Spring 框架中的单例 bean 是线程安全的吗? 不是线程安全的 Spring 框架中有一个 Scope 注解,默认的值是 singleton,即单例的;因为一般在 Spring 的 bean 对象都是无状态的(在生命周期中不被…...
js中的内存泄漏
理解 内存泄漏是计算机,中由于疏忽或者错误造成程序未能释放已经不在使用的内存,知道浏览器结束 垃圾回收机制 js具有自动的垃圾回收机制,垃圾收集器会定期(周期性)的找出那些不在继续使用的变量,然后释放内存 常见的内存泄漏 意外的全局变量 function foo(){bar 123123…...
营业执照年报申报
姿势:营业执照年报申报 借鉴文章:个体工商户年报申报流程(不要再花冤枉钱) 1、国家企业信用信息公示系统 地址:https://www.gsxt.gov.cn/index.html 2、登录(重庆的方式二简单)...
Springboot教程(五)——单元测试
idea中一般使用JUnit进行单元测试 基本使用 我们可以在idea的test文件夹下的XXXXApplicationTests内进行单元测试: 可以在Test标注的方法上写测试代码: SpringBootTest class C0101ApplicationTests {Testfun contextLoads() {println("Hello …...
【Kotlin】函数
1 常规函数 1.1 无参函数 fun main() {myFun() }fun myFun() {println("myFun") // 打印: myFun } 1.2 有参函数 1)常规调用 fun main() {myFun("myFun") // 打印: myFun }fun myFun(str: String) {println(str) } 2)形参指定默…...
Unity生命周期函数解析
本文由 简悦 SimpRead 转码, 原文地址 mp.weixin.qq.com Unity生命周期函数解析 Unity 生命周期函数是在游戏对象的不同阶段被调用的方法,通过这些函数,我们可以在不同的时刻执行特定的代码。在这篇文章中,我们将一步步解析 Unit…...
【Qt】QTextEdit/QPlainTextEdit 实现 Tab 键多行缩进与反缩进
【Qt】QTextEdit/QPlainTextEdit 实现 Tab 键多行缩进与反缩进 文章目录 I - 主要原理II - 代码实现2.1 - 自定义类2.2 - 实现 Tab 缩进2.3 - 实现反缩进 III - 参考链接 I - 主要原理 由于 QTextEdit 和 QPlainTextEdit ,都无法实现多行选中缩进与反缩进ÿ…...
C++缺陷与思考
数组隐式转换为指针 size_t func(int a[10]) {return sizeof(a); }int a[100]; func(a); // 指针大小 sizeof(a); // 数组大小函数的参数看似是一个数组形式,但事实上他已经退化为指针了,也就是等价于size_t func(int* a),而数组作为参数传…...
无公网ip环境使用DS file软件远程访问内网群晖NAS中储存的文件
文章目录 1. 群晖安装Cpolar2. 创建TCP公网地址3. 远程访问群晖文件4. 固定TCP公网地址5. 固定TCP地址连接 DS file 是一个由群晖公司开发的文件管理应用程序,主要用于浏览、访问和管理存储在群晖NAS(网络附加存储)中的文件。这个应用程序具有…...
软件工程基础
本博客地址:https://security.blog.csdn.net/article/details/136446772 一. 软件工程 1、软件危机。具体表现为:软件开发进度难以预测、软件开发成本难以控制、软件功能难以满足用户期望、软件质量无法保证、软件难以维护和软件缺少适当的文档资料。 …...
alzet供应商你值得拥有
在20世纪70年代,ALZE公司研发出来一款巧妙的药物输送装置——Alzet osmotic pump。这款产品如胶囊般精致小巧,它既有胶囊的外表,也具有胶囊的作用。在Alzet osmotic pump中藏有可以装配药物溶液的空间。此款胶囊泵如同一个小投递员࿰…...
x86中的TSS与任务切换
前言 今天在学习《深入理解Linux内核》的时候,发现出现了一个新的名词TSS(Task-State Segment),这还是我第一次了解到原来x86提供了硬件级别的任务切换功能,之前以为任务切换都是操作系统实现的来着,这里也…...
打造去中心化透明储蓄罐:Solidity智能合约的又一实践
一、案例背景 传统的储蓄罐通常是由个人或家庭使用,用于存放硬币或小额纸币。然而,这样的储蓄罐缺乏透明性,用户无法实时了解储蓄情况,也无法确保资金的安全性。 通过Solidity智能合约,我们可以构建一个去中心化…...
Java Mybatis数据库面试题
Java Mybatis数据库面试题 前言1、什么是 Mybatis?2、Mybaits 的优缺点:3、SQL 注入如何防止?4、MyBatis 框架适用场合:5、MyBatis 与 Hibernate 有哪些不同?6、#{}和${}的区别是什么?7、当表中的字段名和实…...
LeetCode-第14题-最长公共前缀
1.题目描述 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 ""。 2.样例描述 3.思路描述 按字符串数组每个数组的长度,将字符串数组从小到大排序;他们的公共前缀一定小于或等于最长元素长度…...
TCP/UDP模型:2024/2/29
作业1:TCP模型 服务器端: #include <myhead.h> #define SER_IP "192.168.199.129" #define SER_PORT 8899int main(int argc, const char *argv[]) {//1.创建用于连接的套接字文件int sfdsocket(AF_INET,SOCK_STREAM,0);if(sfd-1){per…...
微信如何设置自动回复消息,提升沟通效率的?
在日常微信聊天过程中,我们可能会频繁遇到相同问题的客户提问,特别是对于从事销售工作的朋友们而言,客户添加好友后的第一句话常常为“在吗”或“你好”。当我们拥有大量好友,手动逐一回复可能会耗费大量时间。因此,自…...
PCIE的BAR空间
1.PCIe 简介 PCIe(Peripheral Component Interconnect Express)是一种高速 串行计算机扩展总线标准,主要用于连接主板上的中央处理器(CPU)和 各种外部设备,如显卡、声卡、硬盘等。PCIe 总线取代了传统的 PC…...
11.互信息-机器学习模型性能的常用的评估指标
互信息(Mutual Information)是机器学习中常用的一种评估指标,特别是在无监督学习和聚类分析中。它用于衡量两个随机变量之间的相关性或相似性。 定义 给定两个随机变量X和Y,它们的互信息I(X;Y)定义如下: 其中&…...
SpringCloud(18)之Sleuth +Zipkin链路追踪
一、Zipkin介绍 Zipkin是一个开放源代码分布式的跟踪系统,它可以帮助收集服务的时间数据,以解决微服务架构中的延迟问 题,包括数据的收集、存储、查找和展现。每个服务向zipkin报告计时数据,zipkin会根据调用关系通 过Zipkin UI…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
