Spring的三级缓存和SpringMVC的流程

目录

前言

一、Spring的三级缓存

[1. 循环依赖](#1. 循环依赖)

[2. Spring 不支持的循环依赖](#2. Spring 不支持的循环依赖)

[3. 解决循环依赖](#3. 解决循环依赖)

[二、SpringMVC 的流程](#二、SpringMVC 的流程)


前言

Spring通过三级缓存机制解决循环依赖问题:一级缓存存储完整Bean,二级缓存存储半成品Bean,三级缓存存储Bean工厂类。该机制能处理普通循环依赖,但无法解决构造器循环依赖、原型Bean循环依赖和复杂AOP场景下的循环依赖。Spring MVC处理流程包括:请求分发、Handler查找、处理执行、视图解析、视图渲染和结果返回六个步骤。


一、Spring的三级缓存

1. 循环依赖

循环依赖就是 A 对象完成实例化,需要注入 B 对象,B 对象完成实例化,也需要注入 A 对象;只要产生了依赖的闭环,就产生了循环依赖;

Bean 的生命周期分为 5 个步骤,分别是:实例化,属性注入,初始化,使用以及销毁;

在属性注入这个步骤有可能会有循环依赖的问题;

Spring 保存 Bean 是采用缓存的方式,使用一个 Map<String, Object> 的数据结构,key 是 Bean 的名称,value 是 Bean 对象,需要时从缓存中获取;

如果 A 对象和 B 对象互相依赖:

A 进行属性注入的时候,发现缓存中没有 B 对象,于是实例化 B 对象;

实例化 B 对象,进行属性注入的时候,发现缓存中也没有 A 对象,于是实例化 A 对象,于是又重复上面的步骤;

2. Spring 不支持的循环依赖

Spring 能解决循环依赖问题,但也不是能解决全部的情况;

  1. 构造器循环依赖:当两个 Bean 在构造器中循环依赖,会抛出异常 BeanCurrentlyInCreationException;

  2. 原型 Bean 循环依赖:原型作用域的 Bean,生命周期是短暂的,每次使用都会创建一个新的 Bean,因此 Spring 容器中不缓存这样的 Bean,也不能解决循环依赖的问题;

  3. 复杂 AOP 场景下的循环依赖:如果 Bean 存在循环依赖,并且被 AOP 代理,也无法解决;

3. 解决循环依赖

Spring 采用三级缓存解决循环依赖的问题;

一级缓存:用来保存完整的 Bean 对象;

二级缓存:用来保存半成品的对象;

三级缓存:用来保存 Bean 的工厂类;

假设 A 和 B 存在循环依赖:

    1. A 实例化,在属性注入的时候发现需要 B 对象,于是开始实例化 B,并将 A 保存到三级缓存;
    1. B 实例化,在属性注入的时候发现需要 A 对象,于是将 B 的工厂类也放到三级缓存;并调用三级缓存中 A 的工厂类,获取对象,并且把 Bean 放到二级缓存中,删除三级缓存中的工厂类;
    1. B 进行属性注入,从二级缓存中获取 A 对象,初始化完成之后,将 B 对象放到一级缓存;并从二级和三级缓存中删除;
    1. A 进行属性注入,并将对象放到一级缓存,并从二级缓存中删除;

实际上两级缓存就可以解决循环依赖的问题,二级缓存用于保存提前曝光的不完整的 Bean 对象,一级缓存用于保存完整的 Bean 对象;

Spring 使用三级缓存;目的是解决代理相关的循环依赖,使用三级缓存,代码的扩展性更好;

java 复制代码
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    ......

	/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Creation-time registry of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new ConcurrentHashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
}

singletonObjects:一级缓存;

singletonFactories:三级缓存;

earlySingletonObjects:二级缓存;

二、SpringMVC 的流程

SpringMVC的请求响应步骤如下:

具体步骤:

1:(发起)发起请求到前端控制器(DispatcherServlet)

2:(查找)前端控制器请求查找 Handler(可以根据xml配置、注解进行查找)

3:(执行)请求适配器执行处理,并像前端返回 ModelAndView;

4.:(解析)前端进行视图解析;

5:(渲染)前端控制器进行视图渲染;

6:(响应)前端控制器向用户返回结果;


相关推荐
无心水38 分钟前
【OpenClaw:赚钱】案例19、内容产量5倍、广告收入翻4倍:播客转多平台内容矩阵全自动化实战(OpenAI Whisper + Claude)
java·人工智能·python·ai编程·openclaw·养龙虾·java.time
云烟成雨TD1 小时前
Spring AI 1.x 系列【42】MCP 服务端 Spring Boot 启动器
java·人工智能·spring
云烟成雨TD1 小时前
Spring AI 1.x 系列【38】模型上下文协议(MCP)
java·人工智能·spring
Alson_Code1 小时前
Spring AI-1.1.0
java·人工智能·后端·spring·ai编程
小小放舟、1 小时前
@JsonCreator 注解详解——从枚举反序列化说起
spring boot·spring·spring cloud·java-ee·maven·intellij-idea·状态模式
ANnianStriver1 小时前
PetLumina 08 — 通知系统与搜索功能修复(广播机制 + 已读状态 + 参数对齐)
java·ai·ai编程·广播机制
ggaofeng1 小时前
试用zeroclaw
java·开发语言
就叫_这个吧1 小时前
servlet整合tomcat项目启动报错解决,org.apache.tomcat.util.descriptor.web.WebXml.setVersion
java·servlet·tomcat·apache
Wenzar_1 小时前
用 JAX 构建可微分光子神经网络仿真器
java·人工智能·深度学习·神经网络
Java 码思客1 小时前
【Redis分布式缓存实战】第20章 Redis监控运维与自动化体系
运维·redis·缓存