Spring 框架终极教程:从入门到精通
目录
-
第一部分:Spring 基础入门
(图片来源网络,侵删)- 什么是 Spring?
- 为什么选择 Spring?(核心优势)
- Spring 的核心思想:IoC 和 AOP
- 开发环境准备
- 第一个 Spring 程序:Hello World!
-
第二部分:Spring 核心之 IoC (控制反转)
- IoC 是什么?
- Bean 是什么?
ApplicationContext:Spring 的容器- Bean 的配置方式
- XML 配置
- 注解配置 (
@Component,@Service,@Repository,@Controller) - Java 配置 (
@Configuration,@Bean)
- 依赖注入 的三种方式
- 构造器注入
- Setter 注入
- 字段注入 (不推荐)
- Bean 的作用域 和生命周期
-
第三部分:Spring 核心之 AOP (面向切面编程)
- AOP 是什么?(解决什么问题)
- AOP 核心概念:切面、通知、连接点、切入点、目标对象、代理
- 基于 XML 的 AOP 配置
- 基于注解的 AOP 配置 (
@Aspect,@Before,@After,@Around)
-
第四部分:Spring 进阶与常用模块
- Spring JDBC:简化数据库操作
- Spring 事务管理:声明式与编程式事务
- Spring MVC:构建 Web 应用
DispatcherServlet@Controller,@RequestMapping,@RequestParam,@ResponseBody- 视图解析器
- RESTful API 开发
- Spring Boot:现代化的 Spring 开发方式
- Spring Boot 的核心思想(约定大于配置)
- 创建 Spring Boot 项目
- 自动配置 原理
- 常用 Starter 介绍
-
第五部分:学习路径与资源推荐
(图片来源网络,侵删)- 学习路线图
- 推荐书籍
- 推荐在线课程
- 官方文档
第一部分:Spring 基础入门
什么是 Spring?
Spring 是一个开源的、轻量级的 控制反转 和 面向切面编程 的容器框架,它最初由 Rod Johnson 创建,旨在解决企业级应用开发的复杂性。
Spring 就像一个“大管家”,负责管理你应用中的各种对象(比如服务层对象、数据访问层对象等),并负责它们之间的依赖关系。
为什么选择 Spring?(核心优势)
- 非侵入式:你的业务逻辑类可以不依赖 Spring 的任何 API,非常纯粹。
- IoC (控制反转):将对象的创建和依赖关系的维护交给 Spring 容器,你只需使用,无需关心如何创建,这大大降低了组件之间的耦合度。
- AOP (面向切面编程):允许你将横切关注点(如日志、事务、安全)从业务逻辑中分离出来,提高了代码的模块化程度。
- 容器:Spring 是一个 IoC 容器,它负责创建、配置和管理对象(这些对象在 Spring 中被称为 Bean)。
- 一站式框架:Spring 提供了从数据访问、事务管理、Web 开发到安全等一整套解决方案,覆盖了企业级应用开发的方方面面。
- 庞大的社区和生态系统:Spring 拥有非常活跃的社区和丰富的扩展项目(如 Spring Boot, Spring Cloud, Spring Data 等)。
Spring 的核心思想:IoC 和 AOP
- IoC (Inversion of Control - 控制反转):是一种设计思想,传统情况下,对象是自己创建和管理其依赖的对象,而 IoC 则是把这个“控制权”反转给了外部容器(即 Spring),由容器来负责对象的创建、装配和管理,实现 IoC 的最常见方式就是 依赖注入。
- AOP (Aspect-Oriented Programming - 面向切面编程):也是一种编程思想,它是对 OOP(面向对象编程)的补充,OOP 关注的是纵向的继承关系,而 AOP 关注的是横向的、跨越多个对象的通用功能(日志、事务等),AOP 将这些通用功能“切”入到业务逻辑中,而不污染业务代码本身。
开发环境准备
- JDK: 推荐 JDK 8 或更高版本。
- IDE: IntelliJ IDEA (强烈推荐) 或 Eclipse。
- 构建工具: Maven 或 Gradle,这里我们以 Maven 为例。
- Spring Framework: 你可以从 Maven 中央仓库 获取依赖。
第一个 Spring 程序:Hello World!
目标:不通过 new 关键字,而是由 Spring 容器来创建一个对象并调用其方法。
步骤:

-
创建 Maven 项目,并添加 Spring Framework 依赖,在
pom.xml中添加:<dependencies> <!-- 使用 BOM (Bill of Materials) 可以统一管理版本 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.23</version> <!-- 使用一个稳定版本 --> </dependency> </dependencies> -
创建一个普通的 Java 类。
// HelloWorld.java public class HelloWorld { public void sayHello() { System.out.println("Hello, Spring World!"); } } -
配置 Spring 容器,在
src/main/resources目录下创建applicationContext.xml文件。<!-- applicationContext.xml --> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 1. 定义一个 Bean,告诉 Spring 容器要创建 HelloWorld 这个类的对象 --> <!-- id: Bean 的唯一标识符 --> <!-- class: Bean 的全限定类名 --> <bean id="helloWorld" class="com.example.HelloWorld" /> </beans> -
编写主程序,启动 Spring 容器并获取 Bean。
// MainApp.java import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { // 1. 创建 Spring 容器 // ClassPathXmlApplicationContext 会从类路径下查找配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 2. 从容器中获取 Bean // getBean("id", class.class) 方法 HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld"); // 3. 调用对象的方法 helloWorld.sayHello(); } }
运行结果:
Hello, Spring World!
恭喜!你已经成功运行了第一个 Spring 程序,在这个过程中,new HelloWorld() 的操作被 context.getBean("helloWorld") 替代了,对象的创建权交给了 Spring 容器,这就是 IoC 的最简单体现。
第二部分:Spring 核心之 IoC (控制反转)
IoC 是什么?
IoC (Inversion of Control) 是一种设计原则,而不是一种技术,它的核心思想是 将依赖对象的创建和注入过程交给第三方(即 Spring 容器),从而使得业务对象之间解耦。
Bean 是什么?
在 Spring 中,由 Spring IoC 容器实例化、组装和管理的对象称为 Bean,简单说,就是你交给 Spring 管理的 Java 对象。
ApplicationContext:Spring 的容器
ApplicationContext 是 Spring 的核心接口,它代表了 Spring IoC 容器,负责实例化、配置和组装 Bean。
常用的实现类:
ClassPathXmlApplicationContext: 从类路径下加载 XML 配置文件。FileSystemXmlApplicationContext: 从文件系统路径下加载 XML 配置文件。AnnotationConfigApplicationContext: 从 Java 配置类加载(推荐)。
Bean 的配置方式
a. XML 配置(传统方式)
如上例所示,在 applicationContext.xml 中使用 <bean> 标签来定义 Bean。
b. 注解配置(现代方式)
Spring 2.5 引注解,极大简化了配置。
在 XML 中开启注解扫描:
<!-- applicationContext.xml -->
...
<beans ...>
<!-- 扫描 com.example 包及其子包下的所有带有 @Component 注解的类 -->
<context:component-scan base-package="com.example" />
</beans>
然后在类上使用注解:
// @Component 是一个通用注解,表示这个类是一个 Spring Bean
@Component("helloWorld") // 括号内是 Bean 的 ID,可省略,默认为类名首字母小写
public class HelloWorld {
public void sayHello() {
System.out.println("Hello, Spring World with Annotation!");
}
}
还有更细化的注解,用于表示不同层的组件:
@Service: 用于服务层。@Repository: 用于数据访问层。@Controller/@RestController: 用于 Web 层 (MVC)。
c. Java 配置(最推荐的方式)
从 Spring 3.0 开始,推荐使用纯 Java 代码来配置 Spring,完全摒弃 XML。
-
创建配置类,并使用
@Configuration注解。// AppConfig.java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration // 告诉 Spring 这是一个配置类 public class AppConfig { // @Bean 注解告诉 Spring,这个方法会返回一个对象,并将其注册为 Spring 容器中的一个 Bean。 // 方法名默认就是 Bean 的 ID。 @Bean public HelloWorld helloWorld() { return new HelloWorld(); } } -
在主程序中使用
AnnotationConfigApplicationContext。// MainApp.java import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainApp { public static void main(String[] args) { // 直接加载配置类 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); HelloWorld helloWorld = context.getBean(HelloWorld.class); helloWorld.sayHello(); } }
依赖注入 的三种方式
假设我们有两个类:UserService 依赖于 UserDao。
a. 构造器注入(推荐方式)
// UserDao.java
@Repository
public class UserDao {
public void save() {
System.out.println("User data saved to database.");
}
}
// UserService.java
@Service
public class UserService {
private final UserDao userDao; // 使用 final 强调依赖不可变
// 通过构造器注入
@Autowired // 从 Spring 容器中查找并注入 UserDao 类型的 Bean
public UserService(UserDao userDao) {
this.userDao = userDao;
}
public void addUser() {
System.out.println("Adding user...");
userDao.save();
}
}
优点:
- 依赖在对象创建时就被注入,对象状态完整。
- 依赖是
final的,不可变,线程安全。 - 依赖关系在编译时就能检查到,而不是运行时。
b. Setter 注入
// UserService.java
@Service
public class UserService {
private UserDao userDao;
// 通过 Setter 方法注入
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void addUser() {
System.out.println("Adding user...");
userDao.save();
}
}
优点:
- 可选依赖,允许在对象创建后重新配置。
- 适合依赖是可选的或可变的场景。
c. 字段注入(不推荐)
// UserService.java
@Service
public class UserService {
@Autowired // 直接在字段上注入
private UserDao userDao;
public void addUser() {
System.out.println("Adding user...");
userDao.save();
}
}
缺点:
- 违反了依赖倒置原则,代码与 Spring 框架耦合。
- 依赖关系不直观,无法在构造函数中看到。
- 单元测试困难,需要使用反射或 Spring 测试框架来模拟依赖。
Bean 的作用域 和生命周期
-
作用域:
singleton(默认):整个容器中只有一个 Bean 实例。prototype:每次请求都创建一个新的 Bean 实例。request:每个 HTTP 请求创建一个新实例。session:每个 HTTP Session 创建一个新实例。
配置(Java 配置):
@Bean @Scope("prototype") // 指定作用域 public PrototypeBean prototypeBean() { return new PrototypeBean(); } -
生命周期: Spring Bean 的生命周期大致如下:
- 实例化 (
new) - 属性填充 (
@Autowired) - 初始化 (
InitializingBean的afterPropertiesSet方法 或@PostConstruct注解的方法) - 就绪状态
- 销毁 (
DisposableBean的destroy方法 或@PreDestroy注解的方法)
- 实例化 (
第三部分:Spring 核心之 AOP (面向切面编程)
AOP 是什么?(解决什么问题)
假设你的业务代码中有很多日志记录、事务管理、权限检查等代码,它们像胶水一样散布在各个业务方法中,这会导致:
- 代码重复。
- 业务逻辑不纯粹,难以维护。
- 这些“横切”逻辑无法被复用。
AOP 的作用就是将这些横切逻辑分离出来,形成独立的切面,然后通过 Spring 将这些切面“织入”到目标业务方法中。
经典例子:日志。
- 目标对象:
UserService - 通知:在
addUser()方法执行前或后打印日志。 - 切面:一个包含日志逻辑的类。
AOP 核心概念
- Aspect (切面):横切关注点的模块化,比如一个日志切面。
- Join Point (连接点):程序执行的某个特定点,比如方法的调用、异常的抛出,在 Spring AOP 中,连接点仅指方法。
- Pointcut (切入点):匹配连接点的表达式,它定义了哪些连接点(方法)需要被通知。
execution(* com.example.service.*.*(..))。 - Advice (通知):在特定连接点执行的代码,通知有五种类型:
@Before: 在目标方法执行前执行。@After: 在目标方法执行后执行(无论是否发生异常)。@AfterReturning: 在目标方法正常返回后执行。@AfterThrowing: 在目标方法抛出异常后执行。@Around: 在目标方法执行前后都执行,功能最强大。
- Target (目标对象):被通知的对象,如
UserService。 - Proxy (代理):AOP 创建的对象,它包装了目标对象,并在其上添加了通知。
基于 XML 的 AOP 配置(较少使用)
需要开启 AOP 支持:
<!-- applicationContext.xml -->
...
<beans xmlns:aop="http://www.springframework.org/schema/aop">
...
<!-- 开启 AOP 支持 -->
<aop:aspectj-autoproxy />
<!-- 定义目标对象 -->
<bean id="userService" class="com.example.service.UserServiceImpl" />
<!-- 定义切面 -->
<bean id="loggingAspect" class="com.aspect.LoggingAspect" />
<!-- 配置 AOP 切面 -->
<aop:config>
<aop:aspect ref="loggingAspect">
<!-- 定义切入点 -->
<aop:pointcut id="serviceMethod" expression="execution(* com.example.service.*.*(..))" />
<!-- 定义通知 -->
<aop:before pointcut-ref="serviceMethod" method="logBefore" />
</aop:aspect>
</aop:config>
</beans>
基于注解的 AOP 配置(常用)
-
开启 AOP 支持(Java 配置方式):
// AppConfig.java import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @EnableAspectJAutoProxy // 开启基于注解的 AOP 支持 public class AppConfig { // ... 其他 Bean 定义 } -
创建切面类:
// LoggingAspect.java import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component // 切面本身也是一个 Bean @Aspect // 声明这是一个切面 public class LoggingAspect { // 定义一个切入点,可以复用 @Pointcut("execution(* com.example.service.*.*(..))") public void serviceMethod() {} // 通知:在 serviceMethod 这个切入点执行前,执行 logBefore 方法 @Before("serviceMethod()") public void logBefore() { System.out.println("===== AOP: Method is about to be called. Logging... ====="); } // 通知:在指定方法执行后 @After("execution(* com.example.service.UserService.addUser(..))") public void logAfter() { System.out.println("===== AOP: Method has been called. Logging... ====="); } } -
目标对象(与之前相同):
@Service public class UserServiceImpl implements UserService { @Override public void addUser() { System.out.println("Core business logic: Adding a user."); } }
运行结果:
===== AOP: Method is about to be called. Logging... =====
Core business logic: Adding a user.
===== AOP: Method has been called. Logging... =====
第四部分:Spring 进阶与常用模块
Spring JDBC
Spring 提供了 JdbcTemplate,它是对 JDBC 的一次简单封装,可以让你用更简洁的方式操作数据库,而无需处理繁琐的 try-catch-finally 和 Connection 管理。
// 配置数据源
@Bean
public DataSource dataSource() {
// 可以是 H2, MySQL, PostgreSQL 等
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql")
.build();
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
// 在 Service 中使用
@Service
public class UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
public void addUser(String name) {
String sql = "INSERT INTO users (name) VALUES (?)";
jdbcTemplate.update(sql, name); // 自动处理参数和异常
}
}
Spring 事务管理
Spring 提供了声明式和编程式两种事务管理方式。声明式事务(通过注解)是首选。
-
开启事务管理(Java 配置):
@Configuration @EnableTransactionManagement // 开启事务支持 public class AppConfig { // ... 数据源等配置 } -
在 Service 方法上使用
@Transactional:@Service public class UserService { @Autowired private JdbcTemplate jdbcTemplate; @Transactional // 此方法将在一个事务中执行 public void addUsers(String name1, String name2) { jdbcTemplate.update("INSERT INTO users (name) VALUES (?)", name1); // 如果这里发生异常,整个事务会回滚 // int i = 1 / 0; // 取消注释此行,观察数据库变化 jdbcTemplate.update("INSERT INTO users (name) VALUES (?)", name2); } }
Spring MVC
Spring MVC 是一个用于构建 Web 应用程序的框架,它基于 MVC (Model-View-Controller) 设计模式。
-
配置
DispatcherServlet: 在 Java 配置中,@EnableWebMvc和@Configuration会自动配置好DispatcherServlet。 -
创建 Controller:
// UserController.java 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 UserController { @GetMapping("/user") // 处理 GET 请求,路径为 /user @ResponseBody // 直接返回字符串,不进行视图解析 public String getUser(@RequestParam(name = "id", defaultValue = "1") int id) { return "You requested user with ID: " + id; } } -
RESTful API:
@RestController // @Controller + @ResponseBody 的组合 public class UserRestController { @GetMapping("/api/users/{id}") public User getUserById(@PathVariable("id") long id) { // 从数据库获取用户并返回 return new User(id, "John Doe"); } @PostMapping("/api/users") public User createUser(@RequestBody User user) { // 保存用户到数据库 return user; } }
Spring Boot
Spring Boot 不是 Spring 的一个替代品,而是对 Spring 的一次封装和扩展,目的是简化 Spring 应用的初始搭建以及开发过程。
- 核心思想:约定大于配置。
- 核心特性:
- 自动配置:根据你引入的依赖(JAR 包),Spring Boot 会自动为你配置好 Bean,你引入了
spring-boot-starter-web,它会自动配置DispatcherServlet、Tomcat等。 - 起步依赖:将常用的依赖(如 Spring MVC, Tomcat, Jackson)打包成一个
starter,你只需要引入一个starter,就能获得所有相关依赖。 - 内嵌 Web 服务器:无需部署 WAR 文件,可以直接运行一个包含 Tomcat 的 JAR 文件。
- 自动配置:根据你引入的依赖(JAR 包),Spring Boot 会自动为你配置好 Bean,你引入了
创建一个 Spring Boot 项目:
- 访问 start.spring.io。
- 选择 Project: Maven Project。
- 选择 Language: Java。
- 选择 Spring Boot 版本。
- 填写 Group ID 和 Artifact ID。
- 添加依赖:
Spring Web: 用于构建 Web 应用。Spring Data JPA: 用于数据库访问。H2 Database: 一个内存数据库,用于测试。
- 点击 "Generate" 下载项目。
运行:下载后,解压,用 IDEA 打开,找到 SpringTutorialApplication.java 并运行它的 main 方法,一个 Web 服务器就启动了!
第五部分:学习路径与资源推荐
学习路线图
-
基础阶段:
- 理解 IoC 和 AOP 的核心思想。
- 掌握 Spring IoC 容器的使用(Bean 配置、依赖注入)。
- 掌握 Spring AOP 的基本使用(
@Aspect,@Before等)。 - 学会使用
JdbcTemplate进行简单的数据库操作。 - 理解 Spring 事务管理。
-
进阶阶段:
- 深入学习 Spring Boot:这是现代 Java 开发的必备技能,重点掌握自动配置原理、常用
starter、配置文件(application.properties/yml)、Actuator 等。 - Spring Data JPA / MyBatis:学习更高级的 ORM 框架集成。
- Spring Security:学习应用安全控制。
- Spring Cache:学习缓存抽象。
- 深入学习 Spring Boot:这是现代 Java 开发的必备技能,重点掌握自动配置原理、常用
-
高级与生态阶段:
- Spring Cloud:学习微服务架构,包括服务发现、配置中心、网关、熔断等。
- Spring Batch:学习批处理任务。
- 深入源码,理解 Spring 底层实现(如 Bean 的生命周期、循环依赖处理等)。
推荐书籍
- 《Spring实战(第5版)》:经典入门书籍,内容全面,实例丰富。
- 《Spring in Action》(同上,英文版):如果你英文不错,推荐阅读原版。
- 《Spring Boot实战》:专门讲解 Spring Boot 的好书。
推荐在线课程
- B站/慕课网/Udemy:搜索 "Spring Boot"、"Spring 全家桶",有大量免费和付费的优质课程。
- 官方文档:Spring Framework Documentation,Spring Boot Documentation。官方文档永远是最好的学习资料,虽然英文,但非常权威和准确。
官方文档
- Spring Framework: https://docs.spring.io/spring-framework/
- Spring Boot: https://docs.spring.io/spring-boot/
Spring 框架是一个庞大而强大的生态系统,学习它最好的方式就是 动手实践,从一个简单的 Spring Boot 项目开始,逐步添加功能,遇到问题就去查官方文档和源码,不要试图一次性掌握所有内容,循序渐进,你会发现 Spring 会让你的开发工作变得异常高效和愉悦,祝你学习顺利!
