当前位置: 首页 > news >正文

Servlet 和 Spring MVC:区别与联系

前言

在 Java Web 开发中,Servlet 和 Spring MVC 是两个重要的技术。Servlet 是 Java Web 的基础组件,而 Spring MVC 是一个高级 Web 框架,建立在 Servlet 的基础之上,提供了强大的功能和易用性。这篇文章将从定义、原理、功能对比、应用场景等多个方面,详细介绍 Servlet 和 Spring MVC,并解析它们的区别与联系。


一、什么是 Servlet

1. 定义

Servlet 是 Java Web 应用的核心组件,是一种运行在服务器上的小程序,专门用于处理客户端的 HTTP 请求并生成动态响应。Servlet 是 Java EE 规范的一部分,定义了如何通过 Java 编写服务器端的 Web 应用。

2. 工作原理

Servlet 的核心思想是基于 请求-响应模型

  1. 客户端(通常是浏览器)发送 HTTP 请求。
  2. Web 容器(如 Tomcat)将请求路由到 Servlet。
  3. Servlet 处理请求,执行逻辑,生成并返回 HTTP 响应。

3. 核心组件

  • HttpServletRequest:表示客户端的请求对象,包含请求的所有信息(如请求参数、请求头等)。
  • HttpServletResponse:表示服务器的响应对象,包含响应的所有信息(如响应头、响应状态码、响应体等)。

4. Servlet 的生命周期

Servlet 的生命周期由 Web 容器管理,包含以下几个阶段:

  1. 初始化
    • Servlet 第一次被访问时,容器会加载 Servlet 类并调用 init() 方法完成初始化。
  2. 服务
    • 每次请求都会调用 service() 方法,根据请求的 HTTP 方法(GET、POST 等),调用对应的 doGet()doPost() 方法。
  3. 销毁
    • 在服务器关闭或卸载 Servlet 时,调用 destroy() 方法释放资源。

5. 示例代码

以下是一个简单的 Servlet 示例:

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {// 设置响应内容类型resp.setContentType("text/html");// 返回简单的 HTML 响应resp.getWriter().write("<h1>Hello, Servlet!</h1>");}
}

二、什么是 Spring MVC

1. 定义

Spring MVC 是基于 Spring 框架的一个 Web 开发模块,提供了 MVC(Model-View-Controller) 设计模式的完整实现。它简化了 Web 应用开发,提供了对请求映射、参数绑定、视图解析等功能的强大支持。

2. 核心思想

Spring MVC 通过 DispatcherServlet(前端控制器)将所有请求统一拦截并分发给具体的处理器(Controller),然后结合视图(View)生成响应。


3. Spring MVC 的架构

Spring MVC 的核心组件:

  1. DispatcherServlet
    • 前端控制器,负责接收和分发所有 HTTP 请求。
  2. HandlerMapping
    • 请求映射器,将 URL 映射到具体的控制器方法。
  3. Controller
    • 业务处理器,负责执行具体的逻辑。
  4. ModelAndView
    • 数据模型和视图对象,用于封装业务数据和返回的视图信息。
  5. ViewResolver
    • 视图解析器,将逻辑视图名解析为物理视图(如 JSP、Thymeleaf 页面)。
  6. View
    • 负责生成最终的响应内容(HTML、JSON 等)。

4. 工作流程

Spring MVC的工作流程_spring mvc 的工作流程-CSDN博客

  1. 客户端发送请求。
  2. DispatcherServlet 接收请求并委托给 HandlerMapping 找到对应的 Controller 方法。
  3. Controller 方法处理请求,返回数据(Model)和视图(View)。
  4. ViewResolver 将逻辑视图名解析为物理视图。
  5. 将数据渲染到视图,生成响应并返回给客户端。

5. 示例代码

以下是一个简单的 Spring MVC 示例:

Controller 类:

@Controller
public class HelloController {@GetMapping("/hello")@ResponseBodypublic String sayHello(@RequestParam String name) {return "<h1>Hello, " + name + "!</h1>";}
}

三、Servlet 和 Spring MVC 的区别

对比维度ServletSpring MVC
定位Java Web 开发的基础技术。基于 Servlet 构建的高级 Web 框架。
设计思想直接基于 HTTP 请求-响应模型。基于 MVC(Model-View-Controller)设计模式。
开发复杂度较高,需要手动解析请求和生成响应。较低,提供自动化功能(如参数绑定、视图解析)。
功能丰富度功能较少,需要自行实现扩展(如请求映射、数据绑定)。功能丰富,内置请求映射、表单验证、异常处理等功能。
请求映射静态 URL 映射,直接通过 Web 容器配置路由。灵活的动态映射,支持正则表达式、RESTful URL 等。
视图支持需要手动拼接 HTML 或 JSP 页面。支持多种视图技术(JSP、Thymeleaf、JSON 等)。
表单验证需要手动校验参数。提供注解式校验(如 @Valid@NotNull)。
异常处理需要在代码中显式捕获异常并处理。提供全局异常处理机制(如 @ControllerAdvice)。
扩展性扩展性有限,需通过 Filter 或 Listener 实现一些通用功能。提供拦截器机制,支持 AOP 和依赖注入,扩展性极强。
学习曲线入门简单,但复杂项目开发难度大。需要学习 Spring 框架基础,初学者学习曲线稍陡。
适用场景小型项目或需要直接操作 HTTP 请求的场景。中大型项目,特别是需要高扩展性和快速开发的场景。

四、Servlet 和 Spring MVC 的联系

尽管 Servlet 和 Spring MVC 在定位和功能上有所不同,但它们之间有着密切的联系:

1. 基于 Servlet 构建

  • Spring MVC 是构建在 Servlet 基础之上的高级框架。
  • Spring MVC 的核心组件 DispatcherServlet 本质上是一个 Servlet,它负责接收和分发请求。

2. Servlet 是 Spring MVC 的基础

  • Spring MVC 使用 Servlet 来处理 HTTP 请求,但屏蔽了复杂的细节,例如参数解析、请求分发等。

3. Spring MVC 依赖 Servlet 容器

  • Spring MVC 必须运行在支持 Servlet 的 Web 容器(如 Tomcat、Jetty)中。
  • Servlet 容器负责加载和管理 DispatcherServlet

五、什么时候选择 Servlet 或 Spring MVC

1. 使用 Servlet

  • 适合小型项目,功能简单。
  • 希望深入理解 Java Web 的底层原理。
  • 不需要复杂的框架支持,能够手动实现请求处理和响应。

2. 使用 Spring MVC

  • 适合中大型项目,功能复杂。
  • 需要高效开发、灵活配置和良好的扩展能力。
  • 希望享受 Spring 框架的生态系统(如 Spring Data、Spring Security 等)。

示例代码

假设我们需要构建一个简单的 Web 服务:

  • 请求路径:http://localhost:8080/hello?name=Tom
  • 返回内容:Hello, Tom!

完整 Servlet 实现

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;// 使用 @WebServlet 注解映射路径 "/hello"
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {// 初始化 Servlet(只执行一次)@Overridepublic void init() throws ServletException {super.init();System.out.println("Servlet 初始化完成!");}// 处理 GET 请求@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 设置响应内容类型resp.setContentType("text/html;charset=UTF-8");// 获取请求参数String name = req.getParameter("name");if (name == null || name.isEmpty()) {name = "World"; // 默认值}// 返回动态响应resp.getWriter().write("<h1>Hello, " + name + "!</h1>");}// 销毁 Servlet(只执行一次,用于释放资源)@Overridepublic void destroy() {super.destroy();System.out.println("Servlet 已被销毁!");}
}

代码优化点

  1. 注解简化配置:
    • 使用 @WebServlet 注解代替传统的 web.xml 配置。
  2. 默认参数处理:
    • 如果用户未传递参数,返回默认的 "World"。
  3. 字符编码:
    • 通过 resp.setContentType("text/html;charset=UTF-8") 设置字符编码,防止中文乱码。
  4. 日志输出:
    • init()destroy() 方法中添加日志信息,便于调试。

如何运行

  1. 将代码打包为 .war 文件,并部署到 Tomcat。
  2. 访问 URL:http://localhost:8080/hello?name=Tom
  3. 返回结果:Hello, Tom!

Spring MVC 实现

Spring MVC 的实现更加简洁且功能强大。以下代码实现相同的功能。

Controller 类

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class HelloController {// 处理 GET 请求,映射路径 "/hello"@GetMapping("/hello")@ResponseBodypublic String sayHello(@RequestParam(name = "name", required = false, defaultValue = "World") String name) {// 返回动态内容return "<h1>Hello, " + name + "!</h1>";}
}

Spring Boot 主类

如果使用 Spring Boot 构建项目,可以通过以下代码快速启动:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringMvcApplication {public static void main(String[] args) {SpringApplication.run(SpringMvcApplication.class, args);}
}

代码优化点

  1. 注解驱动开发:
    • 使用 @Controller@GetMapping 注解处理请求,简化了配置。
  2. 自动参数绑定:
    • 使用 @RequestParam 自动从请求中提取参数,同时设置默认值。
  3. 自动响应:
    • 通过 @ResponseBody 将返回的字符串直接作为响应体,省去了手动处理 HttpServletResponse
  4. Spring Boot 快速启动:
    • 使用 Spring Boot 自动化配置,无需单独部署到 Tomcat。

如何运行

  1. 将代码保存为一个 Spring Boot 应用。
  2. 运行主类 SpringMvcApplication
  3. 访问 URL:http://localhost:8080/hello?name=Tom
  4. 返回结果:Hello, Tom!

示例场景扩展

为了更好地理解 Servlet 和 Spring MVC 的应用场景,我们再扩展一个功能:根据用户输入返回 JSON 数据。

Servlet 示例(返回 JSON 数据)

import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@WebServlet("/json")
public class JsonServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 设置响应类型为 JSONresp.setContentType("application/json;charset=UTF-8");// 获取请求参数String name = req.getParameter("name");if (name == null || name.isEmpty()) {name = "World";}// 构造响应数据Map<String, String> responseData = new HashMap<>();responseData.put("message", "Hello, " + name + "!");// 将数据转换为 JSONString jsonResponse = new Gson().toJson(responseData);// 返回 JSON 响应resp.getWriter().write(jsonResponse);}
}

Spring MVC 示例(返回 JSON 数据)

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;@RestController
public class JsonController {@GetMapping("/json")public Map<String, String> sayHello(@RequestParam(name = "name", required = false, defaultValue = "World") String name) {// 构造响应数据Map<String, String> response = new HashMap<>();response.put("message", "Hello, " + name + "!");return response;}
}

doGet()doPost()service() 的区别

特性service()doGet()doPost()
定位通用方法,用于处理所有 HTTP 请求类型。专门用于处理 HTTP GET 请求。专门用于处理 HTTP POST 请求。
调用方式由 Web 容器直接调用。service() 方法根据 HTTP 请求方法分发调用。service() 方法根据 HTTP 请求方法分发调用。
实现目的自动分发请求到对应的 doXxx() 方法。处理只读请求(如查询数据)。处理数据提交(如表单、文件上传)。
开发者重写很少被重写,通常由 Web 容器托管。常被重写以处理 GET 请求。常被重写以处理 POST 请求。
请求语义无特定语义,作为分发入口。遵循 HTTP GET 请求的语义(幂等)。遵循 HTTP POST 请求的语义(非幂等)。

六、总结

区别

  • Servlet 是 Java Web 开发的基础技术,提供了直接操作 HTTP 请求和响应的能力,适合小型项目或需要深入了解底层原理的场景。
  • Spring MVC 是一个基于 Servlet 的高级 Web 框架,提供了大量的自动化功能和开发便利性,适合中大型项目。

联系

  • Spring MVC 是建立在 Servlet 技术之上的框架,它通过 DispatcherServlet 实现请求的接收和分发。
  • Servlet 是 Spring MVC 的基础,但 Spring MVC 封装了许多底层细节,使开发更高效。

相关文章:

Servlet 和 Spring MVC:区别与联系

前言 在 Java Web 开发中&#xff0c;Servlet 和 Spring MVC 是两个重要的技术。Servlet 是 Java Web 的基础组件&#xff0c;而 Spring MVC 是一个高级 Web 框架&#xff0c;建立在 Servlet 的基础之上&#xff0c;提供了强大的功能和易用性。这篇文章将从定义、原理、功能对…...

【期末复习】三、内存管理

1.物理内存管理 空闲内存管理方式主要分为:等长划分和不等长划分。 内存管理方式 单一连续分区 基本思想:一段时间内只有一个进程在内存。 特点:简单,内存利用率低, 有三种不同的布局: 固定分区 把内存空间分割成若干区域, 称为分区。 每个分区的大小可以相同也可…...

Microsoft Azure Cosmos DB:全球分布式、多模型数据库服务

目录 前言1. Azure Cosmos DB 简介1.1 什么是 Azure Cosmos DB&#xff1f;1.2 核心技术特点 2. 数据模型与 API 支持2.1 文档存储&#xff08;Document Store&#xff09;2.2 图数据库&#xff08;Graph DBMS&#xff09;2.3 键值存储&#xff08;Key-Value Store&#xff09;…...

【Docker】安装registry本地镜像库,开启Https功能

下载镜像 docker pull registry:2 需要启动https功能&#xff0c;就要生成服务端的自签名的证书和私钥&#xff0c;以及在docker客户端安装这个经过签名的证书。 第一步&#xff1a;生成公私钥信息&#xff0c;第二步&#xff0c;制作证书签名申请文件&#xff0c; 第三步&…...

JUC--线程池

线程池 七、线程池7.1线程池的概述7.2线程池的构建与参数ThreadPoolExecutor 的构造方法核心参数线程池的工作原理 Executors构造方法newFixedThreadPoolnewCachedThreadPoolnewSingleThreadExecutornewScheduledThreadPool(int corePoolSize) 为什么不推荐使用内置线程池&…...

后端Java开发:第十一天

第十一天&#xff1a;方法重载 - 理解与应用 今天我们继续深入 Java 的世界&#xff0c;讨论 Java 中的 方法重载&#xff08;Method Overloading&#xff09;。你可能会想&#xff0c;什么是方法重载&#xff1f;简单来说&#xff0c;方法重载允许你在一个类中定义多个同名方…...

基于 GEE 的长时间序列 Landsat 5 影像下载

目录 1 完整代码 2 运行结果 1 完整代码 var LT5 ee.ImageCollection("LANDSAT/LT05/C01/T1"),imageVisParam {"opacity":1,"bands":["B4","B3","B2"],"gamma":1},roi ee.FeatureCollection(&quo…...

Unity-Mirror网络框架从入门到精通之Attributes属性介绍

前言 在现代游戏开发中&#xff0c;网络功能日益成为提升游戏体验的关键组成部分。Mirror是一个用于Unity的开源网络框架&#xff0c;专为多人游戏开发设计。它使得开发者能够轻松实现网络连接、数据同步和游戏状态管理。本文将深入介绍Mirror的基本概念、如何与其他网络框架进…...

软考证书邮寄步骤

一、点击网址 https://www.ruankao.org.cn/ 复制上述网址&#xff0c;粘贴至浏览器中。点击 “报名入口” 。 二、点击入口 选择考试批次。点击你所在考试地点的入口并进入。 三、登录 输入手机号和密码。进行验证。 四、点击基本信息 点击右上角。进入 “基本信息” 。 五、…...

计算机网络 (29)网络地址转换NAT

前言 网络地址转换&#xff08;Network Address Translation&#xff0c;NAT&#xff09;是计算机网络中的一种重要协议&#xff0c;它主要用于将私有IP地址转换为公共IP地址&#xff0c;以实现内部网络与外部网络之间的通信。 一、基本概念 NAT是一种在局域网&#xff08;LAN&…...

nlp培训重点-2

1. 贝叶斯公式 import math import jieba import re import os import json from collections import defaultdictjieba.initialize()""" 贝叶斯分类实践P(A|B) (P(A) * P(B|A)) / P(B) 事件A&#xff1a;文本属于类别x1。文本属于类别x的概率&#xff0c;记做…...

设计模式(1)——面向对象和面向过程,封装、继承和多态

文章目录 一、day11. 什么是面向对象2. 面向对象的三要素&#xff1a;继承、封装和多态2.1 封装**2.1.1 封装的概念****2.1.2 如何实现封装****2.1.3 封装的底层实现**2.1.4 为什么使用封装&#xff1f;&#xff08;好处&#xff09;**2.1.5 封装只有类能做吗&#xff1f;结构体…...

培训机构Day24

今天讲了一些javaee比较过时的技术&#xff0c;虽然已经过时&#xff0c;该学的还得学学。 知识点&#xff1a; http://localhost:8080/demo01/demo1?a1&b2&c3 pattern: /demo1 上下文路径&#xff1a;ContextPath&#xff0c;/demo01&#xff0c;不包含请求参数。 …...

1/7 C++

练习&#xff1a;要求在堆区连续申请5个int的大小空间用于存储5名学生的成绩&#xff0c;分别完成空间的申请、成绩的录入、升序排序、成绩输出函数&#xff0c;并在主程序中完成测试 要求使用new #include <iostream>using namespace std; double *addr_new() {double …...

C语言初阶习题【23】输出数组的前5项之和

1. 题目描述 求Snaaaaaaaaaaaaaaa的前5项之和&#xff0c;其中a是一个数字&#xff0c; 例如&#xff1a;222222222222222 2.思路 分析下&#xff0c;222222222222222&#xff0c;怎么把它每一项算出来 2 210222 22102222 2221022222 我们的多项式就是a a*102&#xff0c;…...

Android audio(1)-音频模块概述

Audio模块是Android系统的重要组成部分,在 Android 中负责音频路由,数据处理,音频控制,音频设备管理/切换。 下面的内容大多翻译自android官网,读者可跳过阅读后面的博客。 一、系统架构 下图说明了音频模块的组成,并指出各组成部分所涉及的相关源代码。所谓架构就是说模…...

园林与消防工程:选择正确工程项目管理软件的重要性

在园林与消防工程领域&#xff0c;选择正确的工程项目管理软件对于提高项目效率、优化资源配置以及确保项目质量至关重要。以下是对园林与消防工程中选择正确工程项目管理软件重要性的详细分析&#xff1a; 1.提升项目管理效率 实时监控与跟踪&#xff1a;工程项目管理软件能够…...

分布式环境下定时任务扫描时间段模板创建可预订时间段

&#x1f3af; 本文详细介绍了场馆预定系统中时间段生成的实现方案。通过设计场馆表、时间段模板表和时间段表&#xff0c;系统能够根据场馆的提前预定天数生成未来可预定的时间段。为了确保任务执行的唯一性和高效性&#xff0c;系统采用分布式锁机制和定时任务&#xff0c;避…...

SQL刷题笔记——高级条件语句

目录 1题目&#xff1a;SQL149 根据指定记录是否存在输出不同情况 2 作答解析 3 知识点 3.1 count函数 3.2 内连接与左连接 1题目&#xff1a;SQL149 根据指定记录是否存在输出不同情况 2 作答解析 #正确答案 select uid, incomplete_cnt, incomplete_rate from (select …...

与 Oracle Dataguard 相关的进程及作用分析

与 Oracle Dataguard 相关的进程及作用分析 目录 与 Oracle Dataguard 相关的进程及作用分析与 Oracle Dataguard 相关的进程及作用分析一、主库的进程1、LGWR 进程2、ARCH进程3、LNS 进程 二、备库的进程1、RFS 进程2、ARCH3、MRP&#xff08;Managed Recovery Process&#x…...

趋势直线指标

趋势直线副图和主图指标&#xff0c;旨在通过技术分析工具帮助交易者识别市场趋势和潜在的买卖点。 副图指标&#xff1a;基于KDJ指标的交易策略 1. RSV值计算&#xff1a; - RSV&#xff08;未成熟随机值&#xff09;反映了当前收盘价在过去一段时间内的相对位置。通过计算当前…...

【JavaEE】Spring事务

目录 一、事务简介二、Spring事务的实现2.1 事务的操作2.2 分类2.2.1 Spring编程式事务2.2.2 Spring 声明式事务 Transactional2.2.2.1 Transactional 详解2.2.2.1.1 rollbackFor2.2.2.1.2 Isolation2.2.2.1.3 propagation 一、事务简介 事务&#xff1a;事务是⼀组操作的集合…...

决策树 GBDT XGBoost LightGBM

一、决策树 1. 决策树有一个很强的假设&#xff1a; 信息是可分的&#xff0c;否则无法进行特征分支 2. 决策树的种类&#xff1a; 2. ID3决策树&#xff1a; ID3决策树的数划分标准是信息增益&#xff1a; 信息增益衡量的是通过某个特征进行数据划分前后熵的变化量。但是&…...

云原生微服务架构演进之路:理念、挑战与实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言&#xff1a;架构的演进是业务进化的技术反射 在软件行业的发展过程中&#xff0c;架构变迁总是伴随着技术浪潮与业务复杂度的升…...

Maven---配置本地仓库

目录 5. 5.1在Maven路径下新建文件夹用于本地仓库存储 5.2 复制本地仓库路径 5.3 找到配置文件路径&#xff0c;使用VSCode方式打开 5.4 新增一行代码 5.5 复制本地仓库路径&#xff0c;设置存储路径 5.1在Maven路径下新建文件夹用于本地仓库存储 5.2 复制本地仓库路径 5…...

Flutter、React Native、Unity 下的 iOS 性能与调试实践:兼容性挑战与应对策略(含 KeyMob 工具经验)

移动端跨平台开发逐渐成为常态&#xff0c;Flutter、React Native、Unity、Hybrid App 等框架在各类 iOS 项目中频繁出现。但随之而来的&#xff0c;是一系列在 iOS 设备上调试难、性能数据采集难、日志整合难的问题。 今天这篇文章&#xff0c;我从实际项目出发&#xff0c;聊…...

使用 Let‘s Encrypt 和 Certbot 为 Cloudflare 托管的域名申请 SSL 证书

一、准备工作 1. 确保域名解析在 Cloudflare 确保你的域名 jessi53.com 和 www.jessi53.com 的 DNS 记录已经正确配置在 Cloudflare 中&#xff0c;并且状态为 Active。 2. 安装 Certbot 在你的服务器上安装 Certbot 和 Cloudflare 插件。以下是基于 Debian/Ubuntu 和 Cent…...

力扣每日一题——找到离给定两个节点最近的节点

目录 题目链接&#xff1a;2359. 找到离给定两个节点最近的节点 - 力扣&#xff08;LeetCode&#xff09; 题目描述 解法一&#xff1a;双指针路径交汇法​ 基本思路 关键步骤 为什么这样可行呢我请问了&#xff1f; 举个例子 特殊情况 Java写法&#xff1a; C写法&a…...

Windows最快速打开各项系统设置大全

目录 一、应用背景 二、设置项打开方法 2.1 方法一界面查找&#xff08;最慢&#xff09; 2.2 方法二cmd命令&#xff08;慢&#xff09; 2.3 方法三快捷键&#xff08;快&#xff09; 2.4 方法四搜索栏&#xff08;快&#xff09; 2.5 方法五任务栏&#xff08;最快&am…...

FactoryBean 接口

Spring 框架中 FactoryBean 接口的特性&#xff0c;这是 Spring 提供的一种特殊机制&#xff0c;用于创建和管理复杂 Bean。让我通过示例和解释帮您理解这个概念。 一、FactoryBean 是什么&#xff1f; FactoryBean 是 Spring 框架提供的一个工厂接口&#xff0c;用于创建复杂…...