杰瑞科技汇

Spring框架教程该怎么学?

Spring 框架终极教程:从入门到精通

目录

  1. 第一部分:Spring 基础入门

    Spring框架教程该怎么学?-图1
    (图片来源网络,侵删)
    • 什么是 Spring?
    • 为什么选择 Spring?(核心优势)
    • Spring 的核心思想:IoC 和 AOP
    • 开发环境准备
    • 第一个 Spring 程序:Hello World!
  2. 第二部分:Spring 核心之 IoC (控制反转)

    • IoC 是什么?
    • Bean 是什么?
    • ApplicationContext:Spring 的容器
    • Bean 的配置方式
      • XML 配置
      • 注解配置 (@Component, @Service, @Repository, @Controller)
      • Java 配置 (@Configuration, @Bean)
    • 依赖注入 的三种方式
      • 构造器注入
      • Setter 注入
      • 字段注入 (不推荐)
    • Bean 的作用域 和生命周期
  3. 第三部分:Spring 核心之 AOP (面向切面编程)

    • AOP 是什么?(解决什么问题)
    • AOP 核心概念:切面、通知、连接点、切入点、目标对象、代理
    • 基于 XML 的 AOP 配置
    • 基于注解的 AOP 配置 (@Aspect, @Before, @After, @Around)
  4. 第四部分:Spring 进阶与常用模块

    • Spring JDBC:简化数据库操作
    • Spring 事务管理:声明式与编程式事务
    • Spring MVC:构建 Web 应用
      • DispatcherServlet
      • @Controller, @RequestMapping, @RequestParam, @ResponseBody
      • 视图解析器
      • RESTful API 开发
    • Spring Boot:现代化的 Spring 开发方式
      • Spring Boot 的核心思想(约定大于配置)
      • 创建 Spring Boot 项目
      • 自动配置 原理
      • 常用 Starter 介绍
  5. 第五部分:学习路径与资源推荐

    Spring框架教程该怎么学?-图2
    (图片来源网络,侵删)
    • 学习路线图
    • 推荐书籍
    • 推荐在线课程
    • 官方文档

第一部分: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 将这些通用功能“切”入到业务逻辑中,而不污染业务代码本身。

开发环境准备

  1. JDK: 推荐 JDK 8 或更高版本。
  2. IDE: IntelliJ IDEA (强烈推荐) 或 Eclipse。
  3. 构建工具: Maven 或 Gradle,这里我们以 Maven 为例。
  4. Spring Framework: 你可以从 Maven 中央仓库 获取依赖。

第一个 Spring 程序:Hello World!

目标:不通过 new 关键字,而是由 Spring 容器来创建一个对象并调用其方法。

步骤

Spring框架教程该怎么学?-图3
(图片来源网络,侵删)
  1. 创建 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>
  2. 创建一个普通的 Java 类

    // HelloWorld.java
    public class HelloWorld {
        public void sayHello() {
            System.out.println("Hello, Spring World!");
        }
    }
  3. 配置 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>
  4. 编写主程序,启动 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。

  1. 创建配置类,并使用 @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();
        }
    }
  2. 在主程序中使用 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 的生命周期大致如下:

    1. 实例化 (new)
    2. 属性填充 (@Autowired)
    3. 初始化 (InitializingBeanafterPropertiesSet 方法 或 @PostConstruct 注解的方法)
    4. 就绪状态
    5. 销毁 (DisposableBeandestroy 方法 或 @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 配置(常用)

  1. 开启 AOP 支持(Java 配置方式):

    // AppConfig.java
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    @Configuration
    @EnableAspectJAutoProxy // 开启基于注解的 AOP 支持
    public class AppConfig {
        // ... 其他 Bean 定义
    }
  2. 创建切面类

    // 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... =====");
        }
    }
  3. 目标对象(与之前相同):

    @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-finallyConnection 管理。

// 配置数据源
@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 提供了声明式和编程式两种事务管理方式。声明式事务(通过注解)是首选。

  1. 开启事务管理(Java 配置):

    @Configuration
    @EnableTransactionManagement // 开启事务支持
    public class AppConfig {
        // ... 数据源等配置
    }
  2. 在 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) 设计模式。

  1. 配置 DispatcherServlet: 在 Java 配置中,@EnableWebMvc@Configuration 会自动配置好 DispatcherServlet

  2. 创建 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;
        }
    }
  3. 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,它会自动配置 DispatcherServletTomcat 等。
    • 起步依赖:将常用的依赖(如 Spring MVC, Tomcat, Jackson)打包成一个 starter,你只需要引入一个 starter,就能获得所有相关依赖。
    • 内嵌 Web 服务器:无需部署 WAR 文件,可以直接运行一个包含 Tomcat 的 JAR 文件。

创建一个 Spring Boot 项目

  1. 访问 start.spring.io
  2. 选择 Project: Maven Project
  3. 选择 Language: Java
  4. 选择 Spring Boot 版本。
  5. 填写 Group ID 和 Artifact ID。
  6. 添加依赖:
    • Spring Web: 用于构建 Web 应用。
    • Spring Data JPA: 用于数据库访问。
    • H2 Database: 一个内存数据库,用于测试。
  7. 点击 "Generate" 下载项目。

运行:下载后,解压,用 IDEA 打开,找到 SpringTutorialApplication.java 并运行它的 main 方法,一个 Web 服务器就启动了!


第五部分:学习路径与资源推荐

学习路线图

  1. 基础阶段

    • 理解 IoC 和 AOP 的核心思想。
    • 掌握 Spring IoC 容器的使用(Bean 配置、依赖注入)。
    • 掌握 Spring AOP 的基本使用(@Aspect, @Before 等)。
    • 学会使用 JdbcTemplate 进行简单的数据库操作。
    • 理解 Spring 事务管理。
  2. 进阶阶段

    • 深入学习 Spring Boot:这是现代 Java 开发的必备技能,重点掌握自动配置原理、常用 starter、配置文件(application.properties/yml)、Actuator 等。
    • Spring Data JPA / MyBatis:学习更高级的 ORM 框架集成。
    • Spring Security:学习应用安全控制。
    • Spring Cache:学习缓存抽象。
  3. 高级与生态阶段

    • Spring Cloud:学习微服务架构,包括服务发现、配置中心、网关、熔断等。
    • Spring Batch:学习批处理任务。
    • 深入源码,理解 Spring 底层实现(如 Bean 的生命周期、循环依赖处理等)。

推荐书籍

  • 《Spring实战(第5版)》:经典入门书籍,内容全面,实例丰富。
  • 《Spring in Action》(同上,英文版):如果你英文不错,推荐阅读原版。
  • 《Spring Boot实战》:专门讲解 Spring Boot 的好书。

推荐在线课程

  • B站/慕课网/Udemy:搜索 "Spring Boot"、"Spring 全家桶",有大量免费和付费的优质课程。
  • 官方文档Spring Framework DocumentationSpring Boot Documentation官方文档永远是最好的学习资料,虽然英文,但非常权威和准确。

官方文档

Spring 框架是一个庞大而强大的生态系统,学习它最好的方式就是 动手实践,从一个简单的 Spring Boot 项目开始,逐步添加功能,遇到问题就去查官方文档和源码,不要试图一次性掌握所有内容,循序渐进,你会发现 Spring 会让你的开发工作变得异常高效和愉悦,祝你学习顺利!

分享:
扫描分享到社交APP
上一篇
下一篇