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

Spring框架重点概述

在当今的软件开发领域,企业级应用系统往往需要面对复杂的业务逻辑、高并发的访问量以及灵活多变的业务需求。如何构建一个高内聚、低耦合、易维护、可扩展的应用框架,成为众多开发者关注的核心问题。

Spring 框架自 2002 年由 Rod Johnson 提出以来,凭借其轻量级、非侵入性、松耦合的设计理念,迅速成为 Java 开发领域的事实标准。它不仅提供了 IoC(控制反转)AOP(面向切面编程) 这样的核心功能,还涵盖了 数据访问、事务管理、Web 框架(Spring MVC)、测试支持、与第三方框架的整合 等多个方面。

本文将围绕 Spring 框架的重点内容进行系统性阐述,涵盖 核心容器、Bean 管理、IoC、AOP、数据访问与事务管理、Web 框架、测试支持 等内容,旨在帮助读者全面理解 Spring 的设计思想和应用价值,从而在实际开发中更好地运用这一框架。

Spring 的设计哲学可以概括为以下几点:

  1. 解耦合:通过 IoC 容器降低对象之间的依赖。

  2. 关注点分离:通过 AOP 将横切逻辑(如日志、安全、事务)与业务逻辑解耦。

  3. 一致性:提供统一的编程模型,屏蔽不同技术栈之间的差异。

  4. 模块化:整个框架由多个模块组成,可以按需引入,不必全部使用。

官方文档:Spring Framework 文档 :: Spring Framework - Spring 框架

一、核心容器

1.1 核心容器简介

Spring 核心容器(Core Container) 是整个 Spring 框架的基石,负责 管理对象(Bean)的生命周期,并为上层模块(如 AOP、事务、Spring MVC)提供基础支持。

核心容器由以下模块组成:

  1. spring-core:提供基本工具类(如资源加载、类型转换等)。

  2. spring-beans:定义 Bean 的配置、创建和依赖注入。

  3. spring-context:在 core 和 beans 基础上,提供类似 JNDI 注册、国际化、事件机制等功能。

  4. spring-expression(SpEL):Spring 表达式语言,支持在运行时动态获取对象属性、方法调用等。

其核心接口是 ApplicationContext,它是 Spring IoC 容器的实现类。


1.2 核心容器的作用

  1. 实例化和管理 Bean

    • 容器负责根据配置文件(XML)、注解或 Java 配置类来创建对象(Bean)。

    • 统一管理 Bean 的生命周期(创建、初始化、销毁)。

  2. 依赖注入(DI)

    • 容器根据配置为 Bean 注入依赖对象,而不是由代码手动创建。

  3. 配置与解耦

    • 将对象的依赖关系配置在 XML、注解或 Java 类中,避免硬编码。

  4. 扩展支持

    • 提供国际化、事件发布/监听、资源加载等企业级功能。

1.3 代码示例

 使用 XML 配置 Bean

(1)applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义 UserRepository --><bean id="userRepository" class="com.example.repository.UserRepository"/><!-- 定义 UserService,并注入 UserRepository --><bean id="userService" class="com.example.service.UserService"><property name="userRepository" ref="userRepository"/></bean></beans>

(2)Java 代码

// Repository 层
public class UserRepository {public void save(String name) {System.out.println("保存用户:" + name);}
}// Service 层
public class UserService {private UserRepository userRepository;// Setter 注入public void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}public void registerUser(String name) {System.out.println("业务逻辑:注册用户");userRepository.save(name);}
}// 测试
public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = context.getBean("userService", UserService.class);userService.registerUser("Tom");}
}

二、Bean

2.1 什么是 Bean?

在 Spring 中,Bean 指的是由 IoC 容器 管理的对象。
它本质上就是一个 Java 对象,只不过由 Spring 负责:

  • 创建(new 出来)

  • 初始化(赋值、依赖注入)

  • 生命周期管理(初始化回调、销毁回调)

换句话说,任何被 Spring 容器实例化、装配和管理的对象,都是 Spring Bean

2.2 Bean 的定义方式

1. XML 配置方式(传统)
<!-- applicationContext.xml -->
<bean id="userService" class="com.example.service.UserService"><property name="userRepository" ref="userRepository"/>
</bean><bean id="userRepository" class="com.example.repository.UserRepository"/>

对应 Java 代码:

public class UserService {private UserRepository userRepository;public void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}
}
2. 注解方式(现代推荐)
@Service
public class UserService {@Autowiredprivate UserRepository userRepository;
}@Repository
public class UserRepository {}

并在配置类中启用扫描:

@Configuration
@ComponentScan("com.example")
public class AppConfig {}

2.3 Bean 的作用域(Scope)

Spring Bean 默认是 单例模式(singleton),也支持其他作用域:

作用域说明
singleton默认,每个 Spring 容器只创建一个 Bean 实例
prototype每次请求都会创建一个新的 Bean 实例
request每个 HTTP 请求创建一个 Bean(仅 Web 应用有效)
session每个 HTTP 会话创建一个 Bean
application在 ServletContext 级别共享一个 Bean

2.4 Bean 的生命周期

Spring 对 Bean 的管理包括 创建 → 初始化 → 使用 → 销毁

  1. 实例化:Spring 容器通过反射创建对象。

  2. 依赖注入:将依赖对象注入到 Bean 中。

  3. 初始化:如果实现了 InitializingBean 或定义了 @PostConstruct,会在这里调用。

  4. 使用:Bean 被应用程序调用。

  5. 销毁:如果实现了 DisposableBean 或定义了 @PreDestroy,会在容器关闭时执行。

示例:

@Component
public class MyBean implements InitializingBean, DisposableBean {@Overridepublic void afterPropertiesSet() {System.out.println("Bean 初始化完成");}@Overridepublic void destroy() {System.out.println("Bean 被销毁");}
}

也可以用注解:

@Component
public class MyBean {@PostConstructpublic void init() {System.out.println("初始化");}@PreDestroypublic void cleanup() {System.out.println("销毁");}
}

2.5 依赖注入方式

1. 构造器注入
@Component
public class OrderService {private final PaymentService paymentService;@Autowiredpublic OrderService(PaymentService paymentService) {this.paymentService = paymentService;}
}
2. Setter 注入
@Component
public class OrderService {private PaymentService paymentService;@Autowiredpublic void setPaymentService(PaymentService paymentService) {this.paymentService = paymentService;}
}
3. 字段注入
@Component
public class OrderService {@Autowiredprivate PaymentService paymentService;
}

官方建议优先使用 构造器注入,因为它更符合 依赖不可变性 的原则。但企业实际上使用更多的是字段注入,更加方便。

2.6 Bean 的高级特性

1. Bean 的别名
<bean id="userService" class="com.example.UserService" name="us,serviceUser"/>

这样可以用 "userService""us""serviceUser" 获取。


2. 延迟加载(Lazy Initialization)

默认情况下,Spring 会在容器启动时创建所有 singleton Bean。
可以指定 @Lazy,让 Bean 在第一次使用时才创建。

@Component
@Lazy
public class HeavyBean {}
3. Bean 的条件加载

通过 @Conditional 可以控制 Bean 是否注册。

@Configuration
public class AppConfig {@Bean@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")public FeatureService featureService() {return new FeatureService();}
}
4. Bean 的优先级

当有多个候选 Bean 时,可以用 @Primary 指定优先注入,或用 @Qualifier 精确指定。

@Service
@Primary
public class MySQLRepository implements UserRepository {}@Service
public class OracleRepository implements UserRepository {}@Autowired
@Qualifier("oracleRepository")
private UserRepository repository;

三、IOC

3.1 IOC 的定义与原理

IOC(Inversion of Control),即控制反转,是一种设计模式,它的核心思想是将控制权交给外部容器来管理,而不是由应用程序自己控制。简单来说,IOC 就是通过某种方式将对象的创建、依赖关系的注入和生命周期管理交给外部容器来做,常见的容器就是 Spring 的 IoC 容器。

在传统的编程方式中,我们通常直接在类中创建依赖对象,通过硬编码方式来控制对象的实例化和管理。而在 Spring 中,应用的对象(Bean)以及对象之间的依赖关系都由容器负责。容器通过配置(XML 或注解)来描述 Bean 之间的关系,并负责在运行时注入依赖。

IOC 的原理就是反转了应用程序的控制方式,从而使得对象的创建、依赖关系和生命周期管理不再依赖于应用代码本身。这样不仅减少了代码之间的耦合度,也提高了系统的灵活性和可测试性。

3.2 IOC 的实现方式

Spring 提供了多种实现 IOC 的方式,主要通过XML 配置和注解配置两种方式。

3.2.1 XML 配置方式

XML 配置是 Spring 最早的配置方式,它的核心是通过配置文件来定义 Spring 容器中的 Bean 以及它们之间的关系。XML 配置文件通常以 beans.xml 命名,并使用 <bean> 标签来声明 Bean。

在 XML 配置方式下,我们需要在 XML 文件中手动定义 Bean 的信息,Spring 容器根据这些配置来创建和管理 Bean 实例。

XML 配置示例:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义一个 Car Bean --><bean id="car" class="com.example.Car"><property name="make" value="Toyota"/><property name="model" value="Corolla"/></bean><!-- 定义一个 Engine Bean --><bean id="engine" class="com.example.Engine"><property name="type" value="V6"/></bean>
</beans>

在上述 XML 配置中,我们通过 <bean> 标签定义了 Car 和 Engine 两个 Bean,并通过 <property> 标签设置它们的属性。这些配置最终会交给 Spring 容器处理,从而实例化并注入依赖。

3.2.2 注解配置方式

随着 Spring 的发展,注解配置方式成为了更为简洁和便捷的选择。Spring 提供了一些注解,如 @Component、@Autowired、@Configuration 等,可以让我们用更少的代码来进行 Bean 的声明和依赖注入。

使用注解配置方式时,Spring 会通过扫描类路径中的 Bean 注解(如 @Component),自动将其注册到 Spring 容器中。而通过 @Autowired 注解,Spring 会自动注入 Bean 的依赖。

注解配置示例:

import org.springframework.stereotype.Component;@Component
public class Car {private String make;private String model;public String getMake() {return make;}public void setMake(String make) {this.make = make;}public String getModel() {return model;}public void setModel(String model) {this.model = model;}
}@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}

在上面的代码中,@Component 注解将 Car 类标记为一个 Bean,而 @Configuration 和 @ComponentScan 注解指定了包扫描的路径。Spring 容器会扫描指定的包,自动注册所有符合条件的 Bean。

四、AOP

4.1 AOP 的定义与原理

AOP(Aspect-Oriented Programming),即面向切面编程,是一种编程思想,旨在通过分离横切关注点来提高代码的可维护性和可复用性。横切关注点是指那些涉及到多个模块的功能,例如日志、事务、安全等。

AOP 通过定义“切面”(Aspect)来集中处理横切关注点,从而避免在每个模块中都重复编写相同的代码。AOP 的目标是将一些通用的功能模块化,并将其应用到多个不同的模块中。

AOP 的核心概念包括:

  • 切面类(Aspect):该类通过@Aspect注解标记为一个切面类(一个公共模块)。在类中,定义了切入点和通过,比如@Before注解表示该通知再目标方法执行前调用。切面定义了何时、如何以及在哪里应用通知。
  • 连接点(Joinpoint):连接点是程序执行过程中可以插入AOP逻辑的点,通常指方法的执行
  • 通知(Advice):定义了切面的具体操作,表示”做某些事“,包括前置通知(Before)、后置通知(After)、环绕通知(Around)、异常通知(AfterThrowing)、返回通知(AfterReturning)
  • 切入点(Pointcut):@Pointcunt注解标记在一个方法上,定义了在哪执行通知。
  • 织入(Weaving):将切面应用到目标对象的过程。
  • 目标对象:目标对象是指被AOP代理的对象。

4.2 AOP 的实现方式

Spring AOP 提供了基于代理的实现方式。Spring 的 AOP 可以通过两种方式来实现:

  • JDK 动态代理:适用于目标类实现了接口的情况,Spring 会通过 JDK 的反射机制创建目标类的代理对象。
  • CGLIB 代理:当目标类没有实现接口时,Spring 会使用 CGLIB 库通过继承的方式创建目标类的子类。
4.2.1 AOP 的应用

Spring AOP 的常见应用场景包括:

  • 事务管理:AOP 可以在方法执行前后自动管理事务的开启、提交、回滚等操作。
  • 日志记录:AOP 可以用来在方法执行前后记录日志。
  • 性能监控:AOP 可以用来监控方法执行的性能,记录执行时间。

4.3 AOP 的代码示例

通过注解来实现 AOP 非常简便,以下是一个日志记录的 AOP 示例。

@Aspect
@Component
public class LoggingAspect {@Before("execution(* com.example.service.*.*(..))")public void logBefore(JoinPoint joinPoint) {System.out.println("Method " + joinPoint.getSignature().getName() + " is about to be executed");}@After("execution(* com.example.service.*.*(..))")public void logAfter(JoinPoint joinPoint) {System.out.println("Method " + joinPoint.getSignature().getName() + " has been executed");}
}

在这个例子中,@Aspect 注解定义了一个切面,@Before 和 @After 注解则分别在方法执行前后插入日志记录。

五、数据访问与事务管理

在企业级应用开发中,数据访问事务管理 是最核心的部分。传统 JDBC 操作存在以下问题:

  • 代码冗余(需要频繁编写连接获取、关闭、异常处理)。

  • 异常处理复杂(需要捕获并转换 SQLException)。

  • 事务控制困难(需要显式调用 commitrollback)。

Spring 框架通过 统一的 DAO 抽象层JdbcTemplate 工具类声明式事务管理,极大简化了开发者的负担。

5.1 数据访问支持

Spring 提供多种数据访问方式,支持 JDBC、JPA、Hibernate、MyBatis 等主流框架。其核心是提供一致的异常层次结构(DataAccessException),屏蔽底层差异。

1. JdbcTemplate

JdbcTemplate 是 Spring 对 JDBC 的封装,大幅简化了 SQL 操作。

示例代码(查询操作):

@Repository
public class UserRepository {@Autowiredprivate JdbcTemplate jdbcTemplate;// 插入用户public void saveUser(String name, int age) {String sql = "INSERT INTO users (name, age) VALUES (?, ?)";jdbcTemplate.update(sql, name, age);}// 查询用户public User findUserById(int id) {String sql = "SELECT * FROM users WHERE id = ?";return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), id);}// 查询所有用户public List<User> findAllUsers() {String sql = "SELECT * FROM users";return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));}
}

可以看到,JdbcTemplate 自动管理 资源释放(连接、语句、结果集),开发者只需关注 SQL 与业务逻辑。


2. ORM 框架集成(JPA / Hibernate)

Spring 也支持 ORM 框架,例如 JPA。通过 Spring Data JPA,我们可以使用接口操作数据库。

示例代码:

@Entity
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;private String name;private int age;// getter、setter 省略
}public interface UserRepository extends JpaRepository<User, Integer> {User findByName(String name);
}

调用时无需编写 SQL,Spring Data JPA 会根据方法名自动生成查询。

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public void addUser(User user) {userRepository.save(user);}public User getUser(String name) {return userRepository.findByName(name);}
}

5.2 事务管理

在企业应用中,事务管理是保证 数据一致性 的关键。

Spring 提供两种事务管理方式:

  1. 编程式事务管理(手动控制)。

  2. 声明式事务管理(推荐,基于 AOP)。

1. 编程式事务管理

通过 PlatformTransactionManager 手动管理事务,常见于底层灵活场景。

示例代码:

@Service
public class AccountService {@Autowiredprivate JdbcTemplate jdbcTemplate;@Autowiredprivate PlatformTransactionManager transactionManager;public void transfer(int fromId, int toId, double amount) {TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());try {jdbcTemplate.update("UPDATE account SET balance = balance - ? WHERE id = ?", amount, fromId);jdbcTemplate.update("UPDATE account SET balance = balance + ? WHERE id = ?", amount, toId);transactionManager.commit(status); // 提交事务} catch (Exception e) {transactionManager.rollback(status); // 回滚事务throw e;}}
}

虽然灵活,但这种写法显得冗长,不符合“解耦”的理念。


2. 声明式事务管理(推荐)

Spring 通过 AOP 拦截器 自动管理事务,只需使用 @Transactional 注解即可。

示例代码:

@Service
public class AccountService {@Autowiredprivate JdbcTemplate jdbcTemplate;@Transactionalpublic void transfer(int fromId, int toId, double amount) {jdbcTemplate.update("UPDATE account SET balance = balance - ? WHERE id = ?", amount, fromId);// 模拟异常if (true) throw new RuntimeException("转账失败!");jdbcTemplate.update("UPDATE account SET balance = balance + ? WHERE id = ?", amount, toId);}
}

在该例中,如果抛出异常,Spring 会自动回滚事务;如果执行成功,则自动提交。

事务注解常用属性
  • propagation:事务传播行为(如 REQUIREDREQUIRES_NEW)。

  • isolation:事务隔离级别(如 READ_COMMITTEDSERIALIZABLE)。

  • timeout:事务超时时间。

  • readOnly:只读事务优化。

  • rollbackFor:指定哪些异常触发回滚。

3. @Transactional注解的实现逻辑

(1)启动时扫描注解

当Spring容器启动时,TransactionAnnotationParser会扫描@Transactional注解,并将其解析为一个TransactionAttribute对象

(2)创建代理对象

Spring使用AOP为带有@Transactional的类生成代理对象,核心是TransactionInterceptor(事务拦截器)

(3)方法调用拦截

当外部调用代理对象的方法时,事务拦截器会拦截方法调用,拦截器通过TransactionManager来管理事务:判断当前是否存在事务,如果需要新建事务就调用begin( )方法,执行目标方法,方法执行成功则提交事务,异常时根据回滚规则决定是否回滚。

TransactionInterceptor 继承了 MethodInterceptor,核心代码:

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {// 获取事务属性TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);// 获取事务管理器PlatformTransactionManager tm = determineTransactionManager(txAttr);// 开启事务TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);Object retVal;try {// 执行目标方法retVal = invocation.proceed();}catch (Throwable ex) {// 出现异常 -> 回滚completeTransactionAfterThrowing(txInfo, ex);throw ex;}finally {cleanupTransactionInfo(txInfo);}// 提交事务commitTransactionAfterReturning(txInfo);return retVal;
}

六、Web框架(Spring MVC)

6.1 概述

Spring MVC(Model-View-Controller)是 Spring 框架的核心 Web 组件,基于 Servlet API 实现,采用 前端控制器(DispatcherServlet)模式

它的主要目标是:

  • 将请求的处理和视图渲染进行解耦。

  • 提供清晰的分层:控制层(Controller)、服务层(Service)、数据层(DAO)

  • 提供灵活的视图解析,支持 JSP、Thymeleaf、FreeMarker 等。

Spring MVC 的核心就是 DispatcherServlet,它作为前端控制器,负责接收所有请求,并协调各个组件(HandlerMapping、HandlerAdapter、ViewResolver 等)完成处理。


6.2 工作流程

Spring MVC 的请求处理流程如下:

  1. 用户发起请求,例如访问 http://localhost:8080/hello

  2. DispatcherServlet 接收请求(拦截所有以 /.do 结尾的请求)。

  3. HandlerMapping 定位处理器,找到与请求匹配的 Controller 方法。

  4. HandlerAdapter 调用 Controller,执行对应的业务逻辑。

  5. Controller 返回 ModelAndView,包含数据模型和视图名称。

  6. ViewResolver 解析视图,将视图名称解析为实际的页面(如 hello.jsphello.html)。

  7. DispatcherServlet 渲染视图并返回响应

👉 总结:请求进 DispatcherServlet,经过 HandlerMapping 找到 Controller,返回数据给 DispatcherServlet,再由 ViewResolver 渲染视图,最后返回给浏览器。


6.3 核心组件

Spring MVC 主要包含以下组件:

  1. DispatcherServlet:前端控制器,统一入口。

  2. HandlerMapping:根据请求找到对应的处理器(Controller 方法)。

  3. Controller:业务处理核心。

  4. HandlerAdapter:适配器,调用具体的处理器方法。

  5. ModelAndView:包含模型数据和视图信息。

  6. ViewResolver:将逻辑视图名解析为具体的视图实现。

  7. View:最终渲染页面。

七、测试支持

7.1 概述

在企业开发中,测试是保证代码质量的核心环节。Spring 框架自带了一套强大的测试支持,帮助开发者在 单元测试集成测试 中更高效地完成验证工作。

Spring 测试支持主要解决以下几个问题:

  1. 容器管理:测试时可以直接启动 Spring IoC 容器,避免手动实例化 Bean。

  2. 依赖注入:测试类中也可以使用 @Autowired,直接注入 Bean。

  3. 事务管理:测试方法默认事务回滚,避免污染数据库。

  4. Mock 支持:可模拟 Web 请求和响应,进行 Spring MVC 的测试。

  5. 与主流测试框架集成:支持 JUnit 4、JUnit 5、TestNG。


7.2 Spring 测试框架基础

Spring 提供了 spring-test 模块,该模块集成了 JUnit、TestNG,并扩展了对 Spring IoC 容器和事务的支持。

核心注解包括:

  • @RunWith(SpringJUnit4ClassRunner.class):在 JUnit4 中启动 Spring 容器。

  • @ExtendWith(SpringExtension.class):JUnit5 对应的扩展。

  • @ContextConfiguration:指定配置文件或配置类。

  • @SpringBootTest:Spring Boot 项目中常用,启动完整应用上下文。

  • @Transactional:使测试方法运行在事务中,默认回滚。

7.3 测试类型实例

7.3.1 基础示例(JUnit4)

配置类

@Configuration
@ComponentScan("com.example")
public class AppConfig {
}

Service 类

@Service
public class UserService {private final List<String> users = new ArrayList<>();public void addUser(String name) {users.add(name);}public boolean hasUser(String name) {return users.contains(name);}
}

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {@Autowiredprivate UserService userService;@Testpublic void testAddUser() {userService.addUser("Tom");assertTrue(userService.hasUser("Tom"));}
}

说明:

  • @RunWith(SpringJUnit4ClassRunner.class) 让 JUnit 知道需要用 SpringRunner 来执行测试。

  • @ContextConfiguration 告诉测试类如何加载 Spring 配置。

  • @Autowired 可以像在业务代码里一样,直接注入 Bean。

7.3.2 事务回滚测试

Spring 提供了对事务测试的支持。默认情况下,使用 @Transactional 注解的测试方法在执行后会自动回滚,保证数据库不会被污染。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
@Transactional
public class AccountServiceTest {@Autowiredprivate JdbcTemplate jdbcTemplate;@Testpublic void testTransfer() {jdbcTemplate.update("INSERT INTO account (id, balance) VALUES (1, 100)");jdbcTemplate.update("INSERT INTO account (id, balance) VALUES (2, 50)");jdbcTemplate.update("UPDATE account SET balance = balance - 30 WHERE id = ?", 1);jdbcTemplate.update("UPDATE account SET balance = balance + 30 WHERE id = ?", 2);int balance1 = jdbcTemplate.queryForObject("SELECT balance FROM account WHERE id = 1", Integer.class);int balance2 = jdbcTemplate.queryForObject("SELECT balance FROM account WHERE id = 2", Integer.class);assertEquals(70, balance1);assertEquals(80, balance2);}
}

执行完成后,数据库中的插入数据会自动回滚,测试环境干净、可重复。


7.3.3 Spring MVC 测试支持

Spring 提供了 MockMvc 工具,用来模拟 HTTP 请求,不需要启动真实的 Web 服务器即可测试 Controller。

示例代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
@WebAppConfiguration
public class HelloControllerTest {@Autowiredprivate WebApplicationContext wac;private MockMvc mockMvc;@Beforepublic void setup() {mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();}@Testpublic void testHello() throws Exception {mockMvc.perform(get("/hello")).andExpect(status().isOk()).andExpect(model().attribute("msg", "Hello Spring MVC")).andExpect(view().name("hello"));}
}

说明:

  • @WebAppConfiguration 表示测试需要 Web 环境。

  • MockMvc 通过 perform(get("/url")) 发送请求,并验证响应状态、模型数据和视图名称。

7.3.4 Spring Boot 测试支持

在 Spring Boot 中,测试更简洁:

示例代码:

@SpringBootTest
@RunWith(SpringRunner.class)
public class UserServiceBootTest {@Autowiredprivate UserService userService;@Testpublic void testUser() {userService.addUser("Alice");assertTrue(userService.hasUser("Alice"));}
}

说明:

  • @SpringBootTest 会加载完整的 Spring Boot 应用上下文,相当于“全栈启动”,适合集成测试。

  • Spring Boot 还内置了 @DataJpaTest@WebMvcTest 等细化注解,帮助只加载部分上下文,提升测试速度。

总的来说,Spring 框架的成功在于它既有理论上的先进性,又有实践中的易用性。它不仅为开发者提供了构建企业级应用的完整解决方案,还推动了整个 Java 生态的进化。正因如此,Spring 成为现代 Java 开发中不可或缺的重要基石。


文章转载自:

http://7kdEYhmQ.gLnmm.cn
http://FzntK4Sb.gLnmm.cn
http://zct4TkGS.gLnmm.cn
http://oWXoEqID.gLnmm.cn
http://XIQeR3tf.gLnmm.cn
http://3arVTvJJ.gLnmm.cn
http://A73cc5Pu.gLnmm.cn
http://LOLIiNFm.gLnmm.cn
http://mSjlHXF8.gLnmm.cn
http://LXGjzlhx.gLnmm.cn
http://LPG883Ix.gLnmm.cn
http://QaZ2VG1B.gLnmm.cn
http://cgPjT2wR.gLnmm.cn
http://e3FTPl0E.gLnmm.cn
http://9bI9YMQX.gLnmm.cn
http://egVBp5Q1.gLnmm.cn
http://ZCnMxSxR.gLnmm.cn
http://sYrn61tD.gLnmm.cn
http://ApmnlKBM.gLnmm.cn
http://wCfQ3eBi.gLnmm.cn
http://9mHRKvhh.gLnmm.cn
http://Yab8gbIf.gLnmm.cn
http://xx8nClsA.gLnmm.cn
http://uBHhHSEh.gLnmm.cn
http://RvEqxL8x.gLnmm.cn
http://9xRGYpBf.gLnmm.cn
http://jCHyEYtj.gLnmm.cn
http://pHGnMRcl.gLnmm.cn
http://0b8flHbk.gLnmm.cn
http://aYw0f7yR.gLnmm.cn
http://www.dtcms.com/a/373813.html

相关文章:

  • vue2+el的树形穿梭框
  • JuiceFS分布式文件系统
  • 【数据结构】简介
  • MindShow AI:高效生成思维导图的实用AI工具
  • python 通过selenium调用chrome浏览器
  • Spring Cloud Alibaba快速入门02-Nacos(中)
  • Redis集群(redis cluster (去中心化))
  • 无人机航拍数据集|第39期 无人机玉米雄穗目标检测YOLO数据集776张yolov11/yolov8/yolov5可训练
  • PCB下单厂家有哪些?可pcb在线下单厂家
  • 安卓服务的两种启动方式有什么区别
  • Spring Cloud Alibaba 是什么,怎么简单搭建
  • ARM-寄存器与异常处理全解析
  • 2024年6月GESPC++三级真题解析(含视频)
  • 【面试题】Transformer应用实践专题
  • 借助Wisdom SSH,轻松搭建私有云盘
  • Linux基础知识(三)
  • Flink KeyedProcessFunction为什么能为每个key定义State和Timer?
  • 【ARDUINO】通过ESP8266连接WIFI,启动TCP,接受TCP客户端指令【待测试】
  • Azure Data Factory (ADF) vs Azure Logic Apps: 对比分析
  • 软考-系统架构设计师 企业资源规划(ERP)详细讲解
  • 农产品运输与调度服务平台的设计与实现
  • Dart → `.exe`:Flutter 桌面与纯命令行双轨编译完全指南
  • 栈专题之每日温度
  • 远场学习_FDTD_dipole(1)
  • 编译缓存工具 sccache 效果对比
  • 【MFC典型类和函数:CString的字符串魔法与Afx全局函数的便利店】
  • 【MFC】对话框属性:字体 (Font Name) 和 大小 (Font Size)
  • 搜索框设计实用指南:规范、模板与工具全解析
  • Python调用MCP:无需重构,快速为现有应用注入AI与外部服务能力!
  • HTTPS 抓包难点分析,从端口到工具的实战应对