面试笔记——框架篇Spring系列(Spring、SpringMVC、SpringBoot)

news/2024/4/29 9:28:38/文章来源:https://blog.csdn.net/Z__XY_/article/details/136951884

Spring

线程安全

singleton : bean在每个Spring IOC容器中只有一个实例。
prototype:一个bean的定义可以有多个实例。

问题一: Spring中的单例bean是否是线程安全的?

 	@Controller@RequestMapping("/user")public class UserController {private int count;@Autowiredprivate UserService userService;@GetMapping("/getById/{id}")public User getById(@PathVariable("id") Integer id) {count++;System.out.println(count);return userService.getById(id);}}

如上面代码中,成员变量count在getById方法中会发生改变。当多个请求进来时,容器会为每一个请求分配一个线程,多个线程并发执行getById方法,则count会被多次修改,因此需要考虑线程安全问题;同样地,userService依然是一个成员变量,但是,它的状态并不会随请求发生状态改变,因此它不用考虑线程安全。因此,在开发过程中需要尽量避免可修改的成员变量。

Spring bean并没有可变的状态(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。可以通过判断成员变量的状态是否被修改来判断。

因此, Spring中的单例bean不是线程安全的。Spring框架中有一个@Scope注解,默认的值就是singleton,单例的。由于一般在spring的bean的中都是注入无状态的对象,没有线程安全问题,如果在bean中定义了可修改的成员变量,是要考虑线程安全问题的,可以使用多例或者加锁来解决。

AOP 相关

AOP称为面向切面编程, 用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑, 抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性

常见的AOP 使用场景

  • 记录操作日志
  • 缓存处理
  • Spring中内置的事务处理

Spring支持编程式事务管理和声明式事务管理两种方式。

  • 编程式事务控制:需使用TransactionTemplate来进行实现,对业务代码有侵入性,项目中很少使用
  • 声明式事务管理:声明式事务管理建立在AOP之上的。其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
Spring中的事务失效

情况一:异常捕获处理
转账场景:

	@Transactionalpublic void update(Integer from, Integer to, Double money) {try {//转账的用户不能为空Account fromAccount = accountDao.selectById(from);//判断用户的钱是否够转账if (fromAccount.getMoney() - money >= 0) {fromAccount.setMoney(fromAccount.getMoney() - money);accountDao.updateById(fromAccount);//异常int a = 1 / 0;//被转账的用户Account toAccount = accountDao.selectById(to);toAccount.setMoney(toAccount.getMoney() + money);accountDao.updateById(toAccount);}} catch (Exception e) {e.printStackTrace();}}

原因: 事务通知只有捉到了目标抛出的异常,才能进行后续的回滚处理,如果目标自己处理掉异常,事务通知无法知悉。
解决: 在catch块添加throw new RuntimeException(e)抛出

情况二: 抛出检查异常

 	@Transactionalpublic void update(Integer from, Integer to, Double money) throws FileNotFoundException {//转账的用户不能为空Account fromAccount = accountDao.selectById(from);//判断用户的钱是否够转账if (fromAccount.getMoney() - money >= 0) {fromAccount.setMoney(fromAccount.getMoney() - money);accountDao.updateById(fromAccount);//读取文件new FileInputStream("dddd");//被转账的用户Account toAccount = accountDao.selectById(to);toAccount.setMoney(toAccount.getMoney() + money);accountDao.updateById(toAccount);}}

原因: Spring 默认只会回滚非检查异常
解决: 配置rollbackFor属性——@Transactional(rollbackFor=Exception.class)。

情况三: 非public方法导致的事务失效

	@Transactional(rollbackFor = Exception.class)void update(Integer from, Integer to, Double money) throws FileNotFoundException {//转账的用户不能为空Account fromAccount = accountDao.selectById(from);//判断用户的钱是否够转账if (fromAccount.getMoney() - money >= 0) {fromAccount.setMoney(fromAccount.getMoney() - money);accountDao.updateById(fromAccount);//读取文件new FileInputStream("dddd");//被转账的用户Account toAccount = accountDao.selectById(to);toAccount.setMoney(toAccount.getMoney() + money);accountDao.updateById(toAccount);}}

原因: Spring 为方法创建代理、添加事务通知、前提条件都是该方法是 public 的。
解决: 改为 public 方法。

总结:Spring中事务失效的场景及解决方法:

  • 异常捕获处理,自己处理了异常,没有抛出,解决:手动抛出
  • 抛出检查异常,配置rollbackFor属性为Exception
  • 非public方法导致的事务失效,改为public
bean的生命周期

Spring容器是如何管理和创建bean实例方便调试和解决问题。
Spring容器在进行实例化时,会将xml配置的的信息封装成一个BeanDefinition对象,Spring根据BeanDefinition来创建Bean对象,里面有很多的属性用来描述Bean。
在这里插入图片描述
生命周期为:
在这里插入图片描述

  1. 通过BeanDefinition获取bean的定义信息
  2. 调用构造函数实例化bean
  3. bean的依赖注入
  4. 处理Aware接口(BeanNameAware、BeanFactoryAware、ApplicationContextAware)
  5. Bean的后置处理器BeanPostProcessor-前置
  6. 初始化方法(InitializingBean、init-method)
  7. Bean的后置处理器BeanPostProcessor-后置
  8. 销毁bean

Spring 中的循环依赖:
在这里插入图片描述
Spring 的三级缓存:

缓存名称源码名称作用
一级缓存singletonObjects单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象
二级缓存earlySingletonObjects缓存早期的bean对象(生命周期还没走完)
三级缓存singletonFactories缓存的是ObjectFactory,表示对象工厂,用来创建某个对象的

使用三级缓存避免循环依赖的流程:
(A是一个代理对象)
在这里插入图片描述

若在构造方法中出现了循环依赖,如图:
在这里插入图片描述
解决方法: 通过添加@Lazy——进行懒加载,当需要Bean对象的时候再对该对象进行加载。
在这里插入图片描述

Spring框架下常见注解:

注解说明
@Component、@Controller、@Service、@Repository使用在类上用于实例化Bean
@Autowired使用在字段上用于根据类型依赖注入
@Qualifier结合@Autowired一起使用用于根据名称进行依赖注入
@Scope标注Bean的作用范围
@Configuration指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
@ComponentScan用于指定 Spring 在初始化容器时要扫描的包
@Bean使用在方法上,标注将该方法的返回值存储到Spring容器中
@Import使用@Import导入的类会被Spring加载到IOC容器中
@Aspect、@Before、@After、@Around、@Pointcut用于切面编程(AOP)

SpringMVC

Spring MVC(Model-View-Controller)是Spring框架的一个模块,用于构建Web应用程序。它提供了一个设计模式,使开发人员能够将应用程序的业务逻辑(Model)、展示逻辑(View)和请求处理逻辑(Controller)分离开来。
前后端分离下,SpringMVC的执行流程图:
在这里插入图片描述

  1. 客户端发送出请求到前端控制器DispatcherServlet;
  2. DispatcherServlet收到请求调用HandlerMapping(处理器映射器——将请求路径和方法关联起来);
  3. HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet;
  4. DispatcherServlet调用HandlerAdapter(处理器适配器);
  5. HandlerAdapter经过适配调用具体的处理器(Handler/Controller)
  6. 方法上添加了@ResponseBody;
  7. 通过HttpMessageConverter来返回结果转换为JSON并响应。

前后端分离下,SpringMVC的执行流程可以概括为一下步骤:

  1. 接收请求:客户端发起请求时,请求将由前端控制器(通常是Spring MVC中的DispatcherServlet)接收。DispatcherServlet是一个Servlet,负责拦截所有的请求并将它们分发到相应的处理器。

  2. 路由请求:DispatcherServlet根据请求的URL找到相应的处理器(Controller)。在前后端分离的情况下,处理器通常是RESTful控制器,用于处理RESTful API的请求。

  3. 执行处理器:处理器(Controller)执行业务逻辑,通常会调用Service层来处理业务逻辑,并从数据库或其他数据源中获取数据。

  4. 返回响应:处理器(Controller)处理完请求后,会返回一个包含数据的响应对象。在前后端分离的架构中,通常返回的是JSON格式的数据,而不是HTML视图。

  5. 渲染视图:在前后端分离的架构中,视图的渲染通常由客户端负责。客户端收到响应后,使用JavaScript框架(如React、Angular、Vue.js等)来渲染页面并展示数据。

SpringMVC的常用注解

注解说明
@RequestMapping用于映射请求路径,可以定义在类上和方法上。用于类上,则表示类中的所有的方法都是以该地址作为父路径
@RequestBody注解实现接收http请求的json数据,将json转换为java对象
@RequestParam指定请求参数的名称
@PathViriable从请求路径下中获取请求参数(/user/{id}),传递给方法的形式参数
@ResponseBody注解实现将controller方法返回对象转化为json对象响应给客户端
@RequestHeader获取指定的请求头数据
@RestController@Controller + @ResponseBody

SpringBoot

SpringBoot的自动配置原理:

在这里插入图片描述

  • @SpringBootConfiguration:该注解与 @Configuration 注解作用相同,用来声明当前也是一个配置类。
  • @ComponentScan:组件扫描,默认扫描当前引导类所在包及其子包。
  • @EnableAutoConfiguration:SpringBoot实现自动化配置的核心注解。

添加自动配置注解之后,会导入自动配置选择器,如图:
在这里插入图片描述
并不是加载该文件中提到的所有的配置类,而是进行条件加载,如:
在这里插入图片描述
总结:

  • 在Spring Boot项目中的引导类上有一个注解@SpringBootApplication,这个注解是对三个注解进行了封装,分别是:@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan;
  • 其中@EnableAutoConfiguration是实现自动化配置的核心注解,该注解通过@Import注解导入对应的配置选择器。内部就是读取了该项目和该项目引用的Jar包的的classpath路径下META-INF/spring.factories文件中的所配置的类的全类名。 在这些配置类中所定义的Bean会根据条件注解所指定的条件来决定是否需要将其导入到Spring容器中。
  • 条件判断会有像@ConditionalOnClass这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有的Bean放入spring容器中使用。

SpringBoot的常用注解

注解说明
@SpringBootConfiguration组合了- @Configuration注解,实现配置文件的功能
@EnableAutoConfiguration打开自动配置的功能,也可以关闭某个自动配置的选
@ComponentScan Spring组件扫描

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_1028302.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaSE day14笔记

第十四天课堂笔记 课上: 适当做笔记课下 : 总结 , 读代码 , 反复敲代码 , 做练习 数组★★★ 数组 : 存储多个 同一类型 的容器格式 :数组类型 : 引用数据类型, new运算符在堆中 分配一块连续的存储空间 , 系统会给数组元素默认初始化 , 将该数组的引用赋值给数组名 引用数据…

开源 OLAP 及其在不同场景下的需求

目录 一、开源 OLAP 综述 二、OLAP场景思考 2.1 面向客户的报表 2.2 面向经营的报表 2.3 末端运营分析 2.4 用户画像 2.5 订单分析 2.6 OLAP技术需求思考 三、开源数据湖/流式数仓解决方案 3.1 离线数仓体系——Lambda架构 3.2 实时数据湖解决方案 3.3 实时分析解决…

PPP+VPN综合实验

一、实验拓扑 二、实验划分 三、实验需求 四、实验结果 1.配置各端口和pc的IP: pc1: pc2: pc3: pc4: R1: [r1]inter g0/0/0 [r1-GigabitEthernet0/0/0]ip ad 192.168.1.2 24 [r1-GigabitEthernet0/0/0]int s4/0/0…

HCIP —— 多生成树 (MSTP)

MSTP --- Multiple Spanning Tree Protocol --- 802.1s 在 MSTP 中 ,提出了实例的概念,相当于可用让多个VLAN同时属于一个实例,然后只需要一个实例生成一棵树。 --- 一种 VLAN 分流的思想 实例ID :instance ID 由 12位 二进制…

【Chrome控制台】network选项卡的使用

首先打开调试面板「windows:F12;mac:commandoptioni」,找到Network选项卡,其中是对网络相关的数据信息。 录制 控制台内容区域左上角红色按钮就是录制按钮,默认是开启状态,表示监听整个页面运行过程中所产…

Delphi模式编程

文章目录 Delphi模式编程涉及以下几个关键方面:**设计模式的应用****Delphi特性的利用****实际开发中的实践** Delphi模式编程的实例 Delphi模式编程是指在使用Delphi这一集成开发环境(IDE)和Object Pascal语言进行软件开发时,采用…

九河云荣获“华为2024·亚太区年度杰出合作伙伴奖”

2024年3月26日~27日,以“加速智能化,一切皆服务”为主题的华为亚太生态伙伴大会在东莞隆重开幕,九河云作为专业的多云管理服务商,凭借多年来在云领域的赋能发展应邀出席并荣获“亚太区年度杰出伙伴奖”,这不仅彰显了九…

Reactor 模式全解:实现非阻塞 I/O 多路复用

Reactor网络模式是什么? Reactor网络模式时目前网络最常用的网络模式。如果你使用Netty,那么你在使用Reactor;如果你使用Twisted,那么你子啊使用Reactor;如果你使用netpoll,那么你在使用Reactor。 这里先给出答案:Reactor I/O多…

K8S之DaemonSet控制器

DaemonSet控制器 概念、原理解读、应用场景概述工作原理典型的应用场景介绍DaemonSet 与 Deployment 的区别 解读资源清单文件实践案例 概念、原理解读、应用场景 概述 DaemonSet控制器能够确保K8S集群所有的节点都分别运行一个相同的pod副本; 当集群中增加node节…

华为升级FIT AP示例(通过AC的命令行)

升级FIT AP示例(通过AC的命令行) 前提条件 从官网下载升级目标版本对应的系统软件包,保存在PC本地。如果下载的文件是压缩文件,则需要解压缩出系统软件包。 AP已在WAC上线。 背景信息 升级的过程是先将系统软件包传到设备上&…

数据结构基础(三)链表

链表(Linked List)是一种常见的线性数据结构,由一系列称为节点(Node)的元素组成,每个节点包含两部分:数据(Data)和指向下一个节点的引用(Pointer 或者 Link&a…

STM32CubeMX学习笔记27---FreeRTOS事件

一、简介 1、 基本概念 事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,但事件通信只能是事件类型的通信,无数据传输。 与信号量不同的是,它可以实现一对多,多对多的同步。即一个任务可以等待多个事件的…

CentOS使用Docker部署Halo并结合内网穿透实现公网访问本地博客

文章目录 1. Docker部署Halo1.1 检查Docker版本如果未安装Docker可参考已安装Docker步骤:1.2 在Docker中部署Halo 2. Linux安装Cpolar2.1 打开服务器防火墙2.2 安装cpolar内网穿透 3. 配置Halo个人博客公网地址4. 固定Halo公网地址 本文主要介绍如何在CentOS 7系统使…

C语言例4-33:求调和级数中第多少项的值大于10

代码如下&#xff1a; //求调和级数中第多少项的值大于10 //调和级数的第n项为11/21/3...1/n #include<stdio.h> #define LIMIT 10 int main(void) {int n1;float sum0.0;for(;;) //死循环&#xff0c;或者while&#xff08;1&#xff09;{sumsum1.0/n;if(sum&g…

GitLab更新失败(Ubuntu)

在Ubuntu下使用apt更新gitlab报错如下&#xff1a; An error occurred during the signature verification.The repository is not updated and the previous index files will be used.GPG error: ... Failed to fetch https://packages.gitlab.com/gitlab/gitlab-ee/ubuntu/d…

Solidity Uniswap V2 Router swapTokensForExactTokens

最初的router合约实现了许多不同的交换方式。我们不会实现所有的方式&#xff0c;但我想向大家展示如何实现倒置交换&#xff1a;用未知量的输入Token交换精确量的输出代币。这是一个有趣的用例&#xff0c;可能并不常用&#xff0c;但仍有可能实现。 GitHub - XuHugo/solidit…

elasticsearch 8.12+kibana 8.12

准备工作&#xff1a;1.下载相关的安装包放到/usr/local/ES下面 elasticsearch下载地址:Download Elasticsearch | Elastic elasticsearch-head-master下载地址:https://github.com/mobz/elasticsearch-head/archive/master.zip node下载地址:Index of /dist/ kibana地址:Downl…

设计模式之桥接模式解析

桥接模式 1&#xff09;概述 1.定义 桥接模式(Bridge Pattern) 将抽象部分与它的实现部分分离&#xff0c;使它们都可以独立地变化。 2.作用 如果系统中某个类存在两个独立变化的维度&#xff0c;通过该模式可以将这两个维度分离出来&#xff0c;使两者可以独立扩展。 3.…

(一)基于IDEA的JAVA基础5

Scanner的使用 使用scanner可以接收键盘上输入的数据&#xff0c; Scanner inputnew Scanner(System.in)&#xff1b; 导包的方式: 什么是导包&#xff0c;导入的是jdk提供的java开发工具包&#xff0c;我们建一个java文件&#xff0c;psvm快捷输入后&#xff0c;打上new S…

静态住宅IP优缺点,究竟要怎么选?

在进行海外 IP 代理时&#xff0c;了解动态住宅 IP 和静态住宅 IP 的区别以及如何选择合适的类型非常重要。本文将介绍精态住宅 IP 特点和&#xff0c;并提供选择建议&#xff0c;帮助您根据需求做出明智的决策。 静态住宅 IP 的特点 静态住宅 IP 是指 IP 地址在一段时间内保…