每10个Java后端,至少有7个:
会用
@Autowired离不开
@RestController但讲不清
DispatcherServlet到底是谁启动的这不是能力问题,而是 Spring 体系被层层封装,藏得太深。
这篇文章不用新闻腔、不谈「好不好学」「卷不卷」,只做一件事:
把 Spring 体系中 5 个核心模块的关系、边界、核心机制讲清楚。
一、Spring Framework:一切的地基
1.1 要解决的原始问题(纯技术角度)
在没有 Spring 的早期 Java Web 中:
-
对象生命周期由开发者手动管理
-
依赖关系通过
new或工厂模式硬编码 -
事务、日志等横切逻辑散落在业务代码中
Spring 提供两个核心能力从技术上消除这些问题:
IoC(控制反转)
将对象的创建、组装、管理权交给容器。
java
// 传统方式
UserService service = new UserServiceImpl();
service.setDao(new UserDaoImpl());
// Spring 方式
@Component
public class UserService {
@Autowired
private UserDao userDao;
}
AOP(面向切面编程)
将日志、事务、缓存等横切逻辑与业务逻辑分离。
java
@Aspect
@Component
public class LogAspect {
@Before("execution(* com..service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("调用:" + joinPoint.getSignature());
}
}
1.2 Spring Framework 的核心模块划分
| 模块 | 作用 |
|---|---|
| spring-core | IoC 容器基础、Resource 访问 |
| spring-beans | BeanFactory、BeanDefinition |
| spring-context | ApplicationContext、事件、国际化 |
| spring-aop | 代理、拦截器、AOP 基础设施 |
| spring-tx | 声明式事务、事务同步 |
| spring-web | 通用 Web 工具(非 MVC) |
| spring-webmvc | Spring MVC 本身 |
重要理解 :Spring MVC 并不是另一个框架,而是
spring-webmvc模块。
二、Spring MVC:Web 层的具体实现方案
2.1 核心组件(必须记住)
| 组件 | 职责 |
|---|---|
DispatcherServlet |
前端控制器,统一请求入口 |
HandlerMapping |
根据 URL 找到对应 @Controller 的方法 |
HandlerAdapter |
实际调用方法,处理参数、返回值 |
ViewResolver |
解析逻辑视图名到物理视图(JSP、Thymeleaf 等) |
HttpMessageConverter |
JSON / XML / 表单 ↔ Java 对象转换 |
2.2 一次请求的完整链路(经典 8 步)
text
请求 → DispatcherServlet → HandlerMapping → HandlerAdapter
→ Interceptor(前置) → Controller 执行
→ Interceptor(后置) → ViewResolver → 视图渲染 → 响应
2.3 一个最小化的 Spring MVC 配置(XML 时代,理解底层)
xml
<web-app>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
你现在在 Spring Boot 中看不到这个过程,是因为它被自动配置了。
三、Spring Boot:自动配置与启动原理
3.1 核心注解
java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication = 三个注解的合成:
| 注解 | 作用 |
|---|---|
@SpringBootConfiguration |
本质是 @Configuration,表示配置类 |
@EnableAutoConfiguration |
开启自动配置(核心) |
@ComponentScan |
扫描当前包及子包的 @Component |
3.2 自动配置核心机制
-
@EnableAutoConfiguration导入AutoConfigurationImportSelector -
从所有
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中读取配置类 -
根据条件注解(如
@ConditionalOnClass、@ConditionalOnMissingBean)决定是否生效
示例:DataSourceAutoConfiguration 部分逻辑
java
@AutoConfiguration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(DataSource.class)
public class DataSourceAutoConfiguration {
// 只有 classpath 中存在 DataSource,且用户没定义自己的 DataSource 时才生效
}
3.3 Starter 机制的本质
一个 Starter(如 spring-boot-starter-web)只做一件事:
聚合依赖 + 触发自动配置。
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
这个依赖会间接引入:
-
spring-boot-starter(自动配置基础) -
spring-webmvc(Spring MVC) -
tomcat-embed-core(嵌入式 Tomcat) -
jackson(JSON 支持)
四、一张完整的关系与依赖图(可背诵)
text
┌─────────────────────────┐
│ 你的业务代码 │
└───────────┬─────────────┘
│
┌───────────▼─────────────┐
│ Spring Boot Starter │
│ (依赖聚合 + 自动配置) │
└───────────┬─────────────┘
│
┌─────────────────────┼─────────────────────┐
│ │
┌───────▼───────┐ ┌─────────▼─────────┐
│ Spring MVC │ │ 其他 starter 模块 │
│ (webmvc) │ │ (jdbc / redis) │
└───────┬───────┘ └─────────┬─────────┘
│ │
└─────────────────────┬─────────────────────┘
│
┌───────────▼───────────┐
│ Spring Framework │
│ (IoC / AOP / 容器) │
└───────────────────────┘
明确结论:
-
底层永远是 Spring Framework
-
Spring MVC 是一个可选的 Web 实现方案
-
Spring Boot 是配置与启动层,不替代以上两者
五、扩展模块(同样基于 Spring 容器)
5.1 Spring Cloud
定位:分布式 / 微服务架构下的问题解决方案
| 问题 | Spring Cloud 常见方案 |
|---|---|
| 服务注册与发现 | Nacos / Eureka / Consul |
| 配置中心 | Nacos Config / Spring Cloud Config |
| 服务调用 | OpenFeign(声明式 HTTP 客户端) |
| 网关路由 | Spring Cloud Gateway |
| 负载均衡 | Spring Cloud LoadBalancer |
本质理解:
Spring Cloud = 多个 Spring Boot 应用 + 分布式协调能力(基于同一套 Spring 容器模型)
5.2 Spring Data
统一的数据访问抽象:
-
Spring Data JPA
-
Spring Data MongoDB
-
Spring Data Redis
-
Spring Data JDBC
核心特性:统一 Repository 模式,简化数据访问层代码。
java
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByAgeGreaterThan(int age);
}
5.3 Spring Security
认证与授权框架(也是基于 Spring AOP 和 Filter)。
核心组件:
-
SecurityContextHolder -
AuthenticationManager -
UserDetailsService
5.4 Spring AI(2026 重点方向)
官方定位:以 Spring 风格集成 AI 模型
支持的模型:OpenAI、Ollama、Azure OpenAI、HuggingFace
核心能力:
-
声明式
ChatClient -
向量存储抽象(RAG)
-
工具调用(Function Calling)
示例:
java
@RestController
public class AIController {
@Autowired
private ChatClient chatClient;
@GetMapping("/explain")
public String explainSpring() {
return chatClient.prompt()
.user("一句话解释 Spring IoC")
.call()
.content();
}
}
注意:Spring AI 仍然依赖:
-
@Bean管理模型客户端 -
@Configuration配置参数 -
AOP 用于调用拦截
六、技术对比总结表(背熟)
| 模块 | 职责范围 | 独立运行? | 是否依赖 Spring Framework |
|---|---|---|---|
| Spring Framework | IoC、AOP、容器、基础设施 | ✅ 可 | 自身 |
| Spring MVC | Web 请求处理、视图控制 | ❌ | ✅ 依赖 spring-context |
| Spring Boot | 自动配置、启动、环境管理 | ❌ | ✅ 强依赖 |
| Spring Cloud | 分布式协调、微服务 | ❌ | ✅ 依赖 Spring Boot |
| Spring Data | 数据访问统一抽象 | ❌ | ✅ 依赖 |
| Spring Security | 认证授权 | ❌ | ✅ 依赖 |
| Spring AI | LLM 集成、RAG | ❌ | ✅ 依赖 |
七、容器与 Bean 的核心机制(进阶理解)
7.1 BeanFactory vs ApplicationContext
| 接口 | 特点 | 默认采用 |
|---|---|---|
BeanFactory |
延迟加载、轻量 | Spring Boot 底层仍基于它 |
ApplicationContext |
继承 BeanFactory,支持事件、AOP、国际化 | 开发中几乎都用 |
7.2 Bean 的生命周期(完整版)
text
实例化 → 属性赋值 → 初始化前 → 初始化 → 初始化后 → 使用 → 销毁
关键扩展点:
-
BeanPostProcessor -
InitializingBean -
@PostConstruct -
@PreDestroy
7.3 常见 Scope
| Scope | 说明 |
|---|---|
singleton |
默认,一个容器一个实例 |
prototype |
每次请求新实例 |
request |
每个 HTTP 请求 |
session |
每个 HTTP Session |
application |
ServletContext 级别 |
八、常见误区纠正(技术层面)
❌ 误区 1:Spring Boot 是一个独立框架
✅ 正解 :它是一套 配置和组织方案,底层 Bean 管理仍是 Spring Framework。
❌ 误区 2:Spring MVC 已经被淘汰
✅ 正解:在 Spring Boot Web 场景中,默认依然是 Spring MVC,只不过启动方式变了。
❌ 误区 3:Spring Cloud 要掌握所有组件
✅ 正解 :核心理解注册中心 + 配置中心 + 网关即可,其他按需引入。
❌ 误区 4:Spring AI 可以脱离 Spring 使用
✅ 正解:Spring AI 重度依赖 Spring 容器管理客户端、配置、拦截器。
九、自测清单(能答对 80%,算真正理解)
-
@SpringBootApplication包含哪三个注解? -
DispatcherServlet在 Spring Boot 中由谁创建和注册? -
Spring Boot 自动配置的读取路径是什么?
-
Spring MVC 的
HandlerMapping默认实现是什么? -
@Autowired和@Resource的区别是什么? -
如何在不引入 Spring Boot 的情况下单独使用 Spring MVC?
-
Spring Cloud Gateway 和 Spring MVC 的区别是什么?
-
Spring AI 中
ChatClient是如何被注入的?
自测清单答案详解
1. @SpringBootApplication 包含哪三个注解?
答案:
| 注解 | 作用 |
|---|---|
@SpringBootConfiguration |
标识为配置类(本质是 @Configuration) |
@EnableAutoConfiguration |
开启自动配置核心能力 |
@ComponentScan |
扫描当前包及子包的 @Component、@Service、@Repository、@Controller |
源码位置:
org.springframework.boot.autoconfigure.SpringBootApplication
2. DispatcherServlet 在 Spring Boot 中由谁创建和注册?
答案:
由 DispatcherServletAutoConfiguration 自动配置完成。
核心流程:
-
引入
spring-boot-starter-web后,DispatcherServletAutoConfiguration生效 -
通过
@Bean创建DispatcherServlet实例 -
通过
DispatcherServletRegistrationBean将 Servlet 注册到嵌入式 Tomcat 容器中
java
// 简化逻辑
@Bean
@ConditionalOnBean(MultipartResolver.class)
public DispatcherServlet dispatcherServlet() { ... }
@Bean
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet) {
return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
}
3. Spring Boot 自动配置的读取路径是什么?
答案:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
Spring Boot 2.7+ 使用此文件;早期版本使用
spring.factories,3.x 后废弃。
示例文件内容:
text
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Spring Boot 启动时会扫描所有 jar 包中的该文件,加载其中列出的配置类。
4. Spring MVC 的 HandlerMapping 默认实现是什么?
答案:
RequestMappingHandlerMapping
职责:
-
扫描所有
@Controller类中的@RequestMapping注解 -
建立 URL → 处理方法的映射关系(注册到
MappingRegistry)
其他 HandlerMapping 实现(较少使用):
-
BeanNameUrlHandlerMapping:根据 Bean 名称映射 -
SimpleUrlHandlerMapping:显式配置路径映射
5. @Autowired 和 @Resource 的区别是什么?
| 对比维度 | @Autowired |
@Resource |
|---|---|---|
| 所属框架 | Spring | Java 原生(JSR-250) |
| 注入方式 | byType(默认) | byName(默认) |
| 指定名称 | @Qualifier 配合使用 |
name 属性直接指定 |
| 是否必需 | required 属性(默认 true) |
无 required 属性 |
| 适用范围 | 构造器、方法、参数、字段 | 字段、setter 方法 |
示例:
java
@Autowired
@Qualifier("userService")
private UserService service;
@Resource(name = "userService")
private UserService service2;
6. 如何在不引入 Spring Boot 的情况下单独使用 Spring MVC?
答案:
手动创建传统 Java Web 项目,步骤如下:
-
引入依赖:
spring-webmvc(它会传递依赖spring-context、spring-beans等) -
配置
web.xml,注册DispatcherServlet -
编写 spring-mvc.xml 配置:
-
开启组件扫描
<context:component-scan> -
配置视图解析器
InternalResourceViewResolver -
开启注解驱动
<mvc:annotation-driven>
-
-
部署到外部 Tomcat / Jetty
示例 web.xml:
xml
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
这是 Spring Boot 出现前的主流方式,现在通常只用于理解底层原理。
7. Spring Cloud Gateway 和 Spring MVC 的区别是什么?
| 对比维度 | Spring Cloud Gateway | Spring MVC |
|---|---|---|
| 底层服务器 | Netty(非阻塞) | Tomcat / Jetty(阻塞或虚拟线程) |
| 编程模型 | 响应式(WebFlux + Reactor) | 传统 Servlet / 同步 |
| 主要用途 | 网关路由、断言、过滤器 | Web 应用接口开发 |
| 能否共存 | 不建议同时暴露 Gateway 和 MVC | --- |
依赖 spring-boot-starter-web |
❌ 会冲突 | ✅ 需要 |
关键结论:Gateway 不能和
spring-boot-starter-web(MVC)一起用,否则会 Netty 和 Tomcat 冲突。
8. Spring AI 中 ChatClient 是如何被注入的?
答案:
通过 ChatClient.Builder 构建,然后作为 Bean 注入。
典型配置方式:
java
@Configuration
public class AIConfig {
@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
return builder.build();
}
}
使用时直接注入:
java
@Service
public class AIService {
private final ChatClient chatClient;
public AIService(ChatClient chatClient) {
this.chatClient = chatClient;
}
}
原理:
-
Spring AI 自动配置创建
ChatClient.BuilderBean -
开发者可以选择直接注入
Builder或通过Builder.build()创建ChatClient -
二者都是 Spring 容器管理的 Bean,因此支持
@Autowired/ 构造器注入