SpringMVC + SpringBoot 核心知识点总结

SpringMVC + SpringBoot 核心知识点总结

一、SpringMVC 核心原理

1.1 完整请求执行流程

客户端发起请求后,SpringMVC 遵循固定的核心链路完成请求处理、业务执行、响应返回,完整流程如下:

Plain 复制代码
[User Request] 客户端请求
       │
       ▼
1. DispatcherServlet (前端控制器) ───────> 2. HandlerMapping (处理器映射器)
       │                                         │
       │ <─────── 返回 HandlerExecutionChain 处理器链路 ────┘ (匹配目标 Controller)
       ▼
2. HandlerAdapter (处理器适配器)
       │
       ▼
3. Controller (业务控制器) ───> 执行自定义业务逻辑,返回 ModelAndView / JSON 数据
       │
       ▼
4. ViewResolver (视图解析器) ───────> 5. View (视图渲染) ───────> [User Response] 响应返回客户端

1.2 HandlerAdapter 适配器模式核心原理

1.2.1 设计背景

DispatcherServlet 作为 SpringMVC 的核心调度控制器,负责统一接收所有客户端请求。但 SpringMVC 支持多种类型的处理器(Handler),常见三类:

  • 基于 @Controller + @RequestMapping 的注解式控制器(主流常用)

  • 传统实现 Controller 接口的控制器(老旧方式)

  • 实现 HttpRequestHandler 接口的原生 Servlet 处理器

若 DispatcherServlet 直接调用各类 Handler,需要通过大量if-else 判断类型、强转对象、执行对应方法,代码耦合度极高、扩展性极差。

适配器模式的核心作用 :解耦调度器与具体处理器,DispatcherServlet 只对接统一的适配器接口,由适配器适配、执行不同类型的 Handler,实现统一调用、兼容多端

1.2.2 HandlerAdapter 核心源码接口

所有处理器适配器均实现该接口,定义了「适配判断」和「逻辑执行」两大核心能力:

java 复制代码
public interface HandlerAdapter {

    /**
     * 判断当前适配器是否支持该处理器
     * @param handler 目标处理器
     * @return 支持返回true,否则false
     */
    boolean supports(Object handler);

    /**
     * 适配器核心执行方法:内部调用对应处理器的业务逻辑
     * @return ModelAndView 视图与数据模型
     */
    @Nullable
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
    
    // 极少使用:获取资源最后修改时间
    long getLastModified(HttpServletRequest request, Object handler);
}

1.2.3 核心调度流程源码

DispatcherServlet 的 doDispatch 方法是请求调度核心,基于适配器模式完成完整调用:

java 复制代码
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 1. 根据请求路径、参数匹配对应的处理器 Handler
    Object handler = getHandler(request);
    
    // 2. 根据匹配到的 Handler,筛选对应的适配处理器 Adapter
    HandlerAdapter ha = getHandlerAdapter(handler);
    
    // 3. 通过统一适配器接口执行业务逻辑,返回视图模型
    ModelAndView mv = ha.handle(request, response, handler);
    
    // 4. 后续完成视图渲染、响应封装...
}

/**
 * 遍历容器内所有适配器,找到支持当前 Handler 的适配器
 */
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        for (HandlerAdapter adapter : this.handlerAdapters) {
            // 匹配成功则返回对应适配器
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
    }
    throw new ServletException("No adapter for handler [" + handler + "]");
}

1.2.4 自定义适配器加载机制

DispatcherServlet 初始化时,会自动从 Spring 容器中加载所有 HandlerAdapter 实现类,存入内部 handlerAdapters 列表。

SpringBoot 自动加载规则

  1. 自定义适配器类添加 @Component 注解,注册为 Spring Bean;

  2. 保证类被启动类注解扫描范围覆盖;

  3. SpringBoot 启动初始化 DispatcherServlet 时,执行 initHandlerAdapters 方法,自动扫描容器内所有 HandlerAdapter 类型 Bean。

核心扫描源码逻辑:

java 复制代码
// 从Spring容器中获取所有HandlerAdapter实现类
Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
    context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
    this.handlerAdapters = new ArrayList<>(matchingBeans.values());
    // 按照 @Order 注解或 Ordered 接口排序,确定适配器优先级
}

核心结论:只要自定义适配器是 Spring Bean,就会被自动加载至调度器适配器列表,无需手动配置。

二、SpringBoot 核心原理

2.1 自动装配机制(核心)

2.1.1 启动核心注解

SpringBoot 项目启动类的@SpringBootApplication 是组合注解,整合三大核心能力:

  • @SpringBootConfiguration:本质是 @Configuration,标识当前类为全局配置类;

  • @ComponentScan:自动扫描当前包及子包下所有带 @Component、@Service、@RestController 等注解的组件,注入 IOC 容器;

  • @EnableAutoConfiguration自动装配的核心注解,实现按需自动加载框架配置类。

2.1.2 自动装配完整流程

第一步:通过 @Import 导入配置选择器

@EnableAutoConfiguration 底层通过 @Import 引入核心类 AutoConfigurationImportSelector,将其注入 Spring 容器,负责扫描、筛选所有自动配置类。

java 复制代码
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    // ...
}
第二步:SPI 机制扫描配置文件

AutoConfigurationImportSelector 的核心方法 selectImports(),基于 Spring 改良的 SPI 机制,扫描全局 Jar 包配置文件:

  • SpringBoot 2.7+/3.x 新版本 :扫描 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件;

  • SpringBoot 2.6 及以下旧版本 :扫描 META-INF/spring.factories 文件。

文件中预定义了大量框架自动配置类全限定类名,示例:

Plain 复制代码
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

启动时会一次性加载数百个预设自动配置类,等待后续筛选。

第三步:@Conditional 条件按需装配

为避免无脑加载所有配置类导致内存浪费、冲突问题,SpringBoot 通过 @Conditional 系列条件注解,实现按需加载、自动适配

以 Redis 自动配置类为例:

java 复制代码
@AutoConfiguration
@ConditionalOnClass(RedisOperations.class) 
// 条件1:项目引入Redis依赖,Classpath存在对应核心类
@EnableConfigurationProperties(RedisProperties.class) 
// 绑定application.properties/application.yml中Redis配置
public class RedisAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate") 
    // 条件2:用户未自定义redisTemplate Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 自动创建默认RedisTemplate并注入容器
        return new RedisTemplate<>();
    }
}
条件装配核心规则
  1. 未引入对应依赖:@ConditionalOnClass 不生效,配置类直接忽略;

  2. 引入依赖但用户自定义 Bean:@ConditionalOnMissingBean 不生效,优先使用用户自定义配置

  3. 引入依赖且无自定义配置:条件全部命中,SpringBoot 自动创建默认 Bean 注入容器。

2.2 SPI 机制(Service Provider Interface)

2.2.1 核心定义

SPI 是 Java 原生提供的动态服务发现、插件化扩展机制 。核心思想:接口定义固定,实现类动态加载

区别于传统编码方式:

  • 普通面向接口编程:编译期绑定实现类,代码写死,改实现需改代码、重编译;

  • SPI 机制:仅定义标准接口,不绑定任何实现,运行时通过约定配置文件,动态扫描、加载外部 Jar 包中的实现类。

2.2.2 核心作用

  • 普通接口解耦:解决项目内部代码的依赖解耦;

  • SPI 动态解耦:解决框架与第三方扩展 Jar 包的解耦,实现插件化扩展。

2.2.3 传统静态接口编程痛点

常规接口调用方式,编译期强制绑定实现类,扩展性极差:

java 复制代码
// 标准接口
public interface Payment { void pay(); }
// 具体实现类
public class WeChatPayment implements Payment {
    @Override
    public void pay() {}
}

// 调用方式:代码写死实现类,耦合严重
Payment pay = new WeChatPayment();
pay.pay();

即使通过 Spring IOC 注入,也仅能解决项目内部依赖管理,框架层面无法预知未来的第三方扩展实现,无法实现插件化加载。

2.2.4 SPI 动态实现方案

框架仅定义接口,不绑定任何实现,运行时通过 ServiceLoader动态扫描加载所有实现类:

java 复制代码
// 框架层:只定义接口,无任何硬编码实现
public interface Payment { void pay(); }

// SPI动态加载逻辑(运行时自动发现所有实现类)
ServiceLoader<Payment> loaders = ServiceLoader.load(Payment.class);
for (Payment payment : loaders) {
    payment.pay(); // 动态执行所有扩展实现
}

核心价值 :让接口具备跨 Jar 包、跨项目、运行期动态组装的能力,是 SpringBoot、Dubbo、JDBC、Logback 等主流框架核心扩展机制。

相关推荐
GoGeekBaird2 小时前
Anthropic技能"(Skills)的经验分享
后端
王码码20352 小时前
多台服务器怎么统一看状态?Beszel 轻量监控,搭起来不费事
运维·服务器·后端·安全·阿里云·接口·web
郑洁文3 小时前
基于Spring Boot的流浪动物救助网站
java·spring boot·后端·毕设·流浪动物救助
螺丝钉code3 小时前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写
java·人工智能·claude code
指令集梦境4 小时前
Cursor + Spring Boot实战:从零写一个RESTful API
spring boot·后端·restful
摇滚侠5 小时前
Maven 入门+高深 单一架构案例 54-59
java·架构·maven·intellij-idea
VidDown5 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
码云之上5 小时前
聊聊如何设计一个高效、稳定的 Node.js 接入层
前端·后端·node.js
折哥的程序人生 · 物流技术专研5 小时前
Java 23 种设计模式:从踩坑到精通 | 原型模式 —— 克隆对象,深拷贝与浅拷贝的坑你踩过吗?
java·设计模式·架构·原型模式·单一职责原则