spring提供的其他机制

spring提供的其他机制

我把它们整理成了下面这张思维导图,可以先快速建立整体印象:
Spring 核心机制
IoC 容器与 DI
BeanFactory / ApplicationContext
依赖注入 / @Autowired
AOP 面向切面编程
JDK / CGLIB 动态代理
@Aspect / @Before / @After / @Around
数据访问抽象
声明式事务 @Transactional
JDBC / ORM 集成
Web 开发
Spring MVC
RESTful 支持
核心工具与扩展
Spring 表达式语言 SpEL
类型转换与数据校验
Aware 接口体系
响应式编程
Spring WebFlux
Reactive Streams
R2DBC / RSocket
集成与消息
远程调用
JMS / AMQP
JMX
邮件 / 定时任务
测试
Mock 对象
测试上下文 TestContext
@MockBean


1.创建一个线程的机制

2.springevent

3.定时任务@scheduled和springtask相关

4.@retryable

5.国际化相关

6.单元测试相关


1. 创建线程的机制(异步执行与线程池)

Spring 并没有重新发明 Java 的线程,而是通过 TaskExecutor 抽象@Async 注解 提供了声明式的异步执行能力,本质上是对 java.util.concurrent.Executor 的封装。

核心组件

  • TaskExecutor 接口:Spring 的任务执行器抽象
  • ThreadPoolTaskExecutor:最常用的线程池实现(基于 ThreadPoolExecutor
  • @Async:标记异步方法
  • @EnableAsync:启用异步处理

使用步骤

  1. 配置类加 @EnableAsync
  2. 定义自定义线程池 Bean(推荐,避免默认的 SimpleAsyncTaskExecutor
java 复制代码
@Bean(name = "taskExecutor")
public Executor taskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(5);
    executor.setMaxPoolSize(10);
    executor.setQueueCapacity(100);
    executor.setThreadNamePrefix("async-");
    executor.initialize();
    return executor;
}
  1. 在需要异步执行的方法上添加 @Async("taskExecutor")

最佳实践

  • 必须自定义线程池,否则高并发下默认实现会为每个任务创建新线程,导致内存溢出
  • 异步方法的返回值可以是 voidFuture<T>CompletableFuture<T>
  • 自调用(类内部直接调用 @Async 方法)会导致异步失效,需要将异步方法放到独立的 Bean 中

2. Spring 事件(ApplicationEvent & @EventListener)

基于 观察者模式 实现业务解耦,适合在同一个应用内的不同模块间传递消息。

核心组件

  • ApplicationEvent:事件基类,自定义事件需继承它
  • ApplicationEventPublisher:发布事件的接口(通常直接注入)
  • @EventListener:注解在监听方法上
  • ApplicationEventMulticaster:底层事件广播器(通常使用默认的 SimpleApplicationEventMulticaster

使用步骤

  1. 定义事件类:
java 复制代码
public class OrderCreatedEvent extends ApplicationEvent {
    private final Long orderId;
    public OrderCreatedEvent(Object source, Long orderId) {
        super(source);
        this.orderId = orderId;
    }
    // getter...
}
  1. 发布事件:注入 ApplicationEventPublisher,调用 publishEvent
  2. 监听事件:
java 复制代码
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) { ... }

最佳实践

  • 默认同步执行 :事件发布线程会等待所有监听器执行完毕。如需异步,可在监听方法上加 @Async
  • 监听顺序 :使用 @Order 注解
  • 事务绑定 :使用 @TransactionalEventListener 可将监听器与事务阶段绑定(如 AFTER_COMMIT

3. 定时任务(@Scheduled 与 TaskScheduler)

基于 java.util.concurrent.ScheduledExecutorService 的封装,提供方便的任务调度能力。

核心组件

  • @EnableScheduling:启用调度
  • @Scheduled:标记定时方法
  • TaskScheduler:调度器接口(默认实现 ThreadPoolTaskScheduler

使用步骤

  1. 配置类加 @EnableScheduling
  2. 在方法上使用 @Scheduled
java 复制代码
@Scheduled(fixedDelay = 5000)      // 上次结束后延迟5秒
@Scheduled(fixedRate = 5000)       // 上次开始后间隔5秒(可能并发)
@Scheduled(cron = "0 0 * * * ?")   // Cron表达式

最佳实践

  • 默认单线程 :所有定时任务共用同一个线程。若某个任务阻塞,会延迟其他任务。建议自定义 TaskScheduler 并设置线程池大小:
java 复制代码
@Bean
public TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
    scheduler.setPoolSize(5);
    return scheduler;
}
  • fixedRate 注意并发:若任务执行时间超过间隔,可能并发执行,需确保方法线程安全
  • 动态调度:实现 SchedulingConfigurer 可动态修改 Cron 表达式

4. @Retryable 重试机制

用于处理临时故障(网络抖动、数据库死锁等),通过声明式重试提高成功率。

核心组件

  • @EnableRetry:启用重试
  • @Retryable:标记需要重试的方法
  • @Recover:重试耗尽后的降级方法

使用步骤

  1. 添加依赖:spring-retry + spring-boot-starter-aop
  2. 启动类加 @EnableRetry
  3. 在方法上使用:
java 复制代码
@Retryable(value = {DataAccessException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2))
public void callRemoteService() { ... }
  1. 定义恢复方法:
java 复制代码
@Recover
public void recover(DataAccessException e) { ... }

最佳实践

  • 指定明确的异常类型,不要对所有异常重试
  • 合理配置退避策略(backoff),避免重试风暴
  • @Recover 方法参数必须与重试方法抛出的异常匹配,且返回值类型一致

5. 国际化(i18n)相关

Spring 通过 MessageSource 接口提供了完善的国际化支持,可以轻松实现多语言文本管理。

核心组件

  • MessageSource:国际化消息的核心接口
  • ResourceBundleMessageSource:基于资源文件的实现(推荐)
  • ReloadableResourceBundleMessageSource:支持热加载的实现
  • LocaleContextHolder:获取当前请求的 Locale(Web 环境下)

使用步骤

  1. src/main/resources 下创建消息文件:
    • messages.properties(默认)
    • messages_zh_CN.properties(中文)
    • messages_en_US.properties(英文)
  2. 配置 MessageSource Bean:
java 复制代码
@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource source = new ResourceBundleMessageSource();
    source.setBasename("messages");   // 基础名
    source.setDefaultEncoding("UTF-8");
    source.setCacheSeconds(3600);
    return source;
}
  1. 在代码中使用:
    • 注入 MessageSource,调用 getMessage("key", args, locale)
    • 在 Spring MVC 的 View 中,使用 #{}message 标签
    • 在 Thymeleaf 等模板中直接使用 #{key}

最佳实践

  • 明确当前语言环境 :Web 应用中,可通过 LocaleResolver 从请求头、Cookie 或 Session 解析 Locale
  • 支持热加载 :开发时使用 ReloadableResourceBundleMessageSource,方便修改资源文件无需重启
  • 参数化消息 :支持占位符,如 message.key=Hello {0},today is {1}
  • 与国际化配合@Controller 中可接收 Locale 参数,根据前端需求动态切换

6. 单元测试相关(spring-test 模块)

Spring 提供了 spring-test 模块,极大简化了基于 Spring 容器的集成测试编写。

核心组件

  • @RunWith(SpringRunner.class) / @ExtendWith(SpringExtension.class)(JUnit 5)
  • @ContextConfiguration:指定配置文件或配置类
  • @SpringBootTest:Spring Boot 的集成测试注解
  • @MockBean:在容器中替换真实 Bean 为 Mock 对象(基于 Mockito)
  • TestContext 框架:缓存 ApplicationContext,提升测试执行速度

使用步骤(以 JUnit 5 + Spring Boot 为例)

java 复制代码
@SpringBootTest  // 启动完整上下文
@AutoConfigureMockMvc  // 用于测试 MVC 接口
class UserServiceTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @MockBean
    private RemoteService remoteService;  // 替换真实 Bean
    
    @Test
    void testGetUser() throws Exception {
        when(remoteService.call()).thenReturn("mock data");
        mockMvc.perform(get("/user/1"))
               .andExpect(status().isOk());
    }
}

最佳实践

  • 分层测试
    • 单元测试:不启动 Spring 容器,只测试单个类(使用 Mockito)
    • 切片测试:@WebMvcTest(测试 Controller)、@DataJpaTest(测试 Repository)等,只加载部分 Bean,速度快
    • 集成测试:@SpringBootTest 启动完整上下文,可用于测试完整流程
  • 使用 @TestPropertySourceapplication-test.properties 隔离测试环境配置
  • 事务回滚@Transactional 加在测试方法上,默认会在结束后回滚,避免污染数据库
  • 重复利用上下文TestContext 框架会缓存 ApplicationContext,不同测试类若配置相同则复用,注意不要使用 @DirtiesContext

总结对比

机制 核心注解/接口 主要用途 常见陷阱
异步线程 @Async, TaskExecutor 提升响应速度,处理耗时任务 默认线程池无限创建线程;自调用失效
Spring 事件 @EventListener, ApplicationEvent 业务解耦,模块间通信 默认同步阻塞;事件滥用导致理解困难
定时任务 @Scheduled 周期性执行任务 单线程阻塞;fixedRate 并发隐患
重试 @Retryable, @Recover 处理瞬时故障 无退避策略可能加重故障;忘记配置 @EnableRetry
国际化 MessageSource 多语言支持 未正确设置编码;Locale 未传递
单元测试 @SpringBootTest, @MockBean 集成测试,模拟依赖 测试过慢(应优先使用切片测试);上下文污染
相关推荐
阿昌喜欢吃黄桃1 小时前
如果线程池中线程异常后:销毁还是复用?
java·线程·线程池·多线程·juc
奋斗的小乌龟1 小时前
动态创建Agent01
java·笔记
还是鼠鼠1 小时前
AI掘金头条新闻系统 (Toutiao News)-用户注册-创建用户
后端·python·mysql·fastapi·web
彦为君1 小时前
Java文件处理效率库Commons-IO(速览)
java·开发语言·mfc
李广坤2 小时前
别再把 Filter、Interceptor 和 AOP 混为一谈了!从接口加解密谈 Spring 纵深架构设计
后端
我是一颗柠檬2 小时前
【MySQL全面教学】MySQL条件查询与排序Day4(2026年)
数据库·后端·mysql
她的男孩2 小时前
后台权限不只是菜单隐藏:Forge Admin 的 RBAC 权限链路拆解
java·后端·架构
Slow菜鸟2 小时前
Maven 仓库下载机制
java·数据库·maven
一个诺诺前行的后端程序员2 小时前
rag+springai
java·eclipse