济南cms建站,做一款微信小程序多少钱,南昌是哪个省,北京网站的建立的Spring Boot 监听器#xff08;Listeners#xff09;详细教程 目录
Spring Boot 监听器概述监听器核心概念最佳使用场景实现步骤高级配置详细使用场景总结 1. Spring Boot 监听器概述
Spring Boot 监听器#xff08;Listeners#xff09;基于 Spring Framework 的事件机制…Spring Boot 监听器Listeners详细教程 目录
Spring Boot 监听器概述监听器核心概念最佳使用场景实现步骤高级配置详细使用场景总结 1. Spring Boot 监听器概述
Spring Boot 监听器Listeners基于 Spring Framework 的事件机制ApplicationEvent 和 ApplicationListener用于在应用生命周期或自定义事件触发时执行特定逻辑。它们提供了一种松耦合的方式响应应用状态变化常用于初始化资源、监控应用状态、执行异步任务等。
2. 核心概念
2.1 事件类型
内置系统事件 ContextRefreshedEventApplicationContext初始化或刷新时触发ContextStartedEventApplicationContext启动后触发ContextStoppedEventApplicationContext停止后触发ContextClosedEventApplicationContext关闭后触发ApplicationStartedEventSpring Boot应用启动后触发ApplicationReadyEvent应用准备就绪时触发推荐在此执行启动逻辑ApplicationFailedEvent启动失败时触发 自定义事件继承ApplicationEvent创建特定业务事件
2.2 监听器类型
接口实现实现ApplicationListenerEventType注解驱动使用EventListener注解方法SmartApplicationListener支持事件类型过滤和顺序控制
简单说就是
事件Event继承 ApplicationEvent 的类表示一个事件如应用启动、关闭等。监听器Listener实现 ApplicationListener 接口或使用 EventListener 注解的组件用于响应事件。事件发布Publisher通过 ApplicationEventPublisher 发布事件。
3. 最佳使用场景
场景说明应用生命周期管理在应用启动、关闭时初始化或释放资源如数据库连接、线程池。异步任务触发通过事件驱动异步处理如发送邮件、记录日志。业务逻辑解耦模块间通过事件通信避免直接依赖。业务事件处理订单创建通知、日志审计监控与统计监听请求事件统计 API 调用次数、响应时间等。
4. 实现步骤代码示例
4.1 系统事件监听
方式1实现ApplicationListener接口
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;public class SystemStartupListener implements ApplicationListenerApplicationReadyEvent {Overridepublic void onApplicationEvent(ApplicationReadyEvent event) {System.out.println( 应用启动完成执行初始化操作 );// 初始化业务数据...}
}方式2使用EventListener注解
import org.springframework.context.event.EventListener;
import org.springframework.boot.context.event.ApplicationStartedEvent;Component
public class AnnotationBasedListener {EventListenerpublic void handleStartedEvent(ApplicationStartedEvent event) {System.out.println( 应用启动事件捕获 );}
}4.2 自定义事件
步骤1定义事件类
public class OrderCreateEvent extends ApplicationEvent {private String orderId;public OrderCreateEvent(Object source, String orderId) {super(source);this.orderId orderId;}public String getOrderId() {return orderId;}
}步骤2发布事件
Service
public class OrderService {Autowiredprivate ApplicationEventPublisher eventPublisher;public void createOrder(Order order) {// 创建订单逻辑...eventPublisher.publishEvent(new OrderCreateEvent(this, order.getId()));}
}步骤3监听事件
Component
public class OrderEventListener {EventListenerpublic void handleOrderEvent(OrderCreateEvent event) {System.out.println(收到订单创建事件订单ID event.getOrderId());// 发送通知、更新统计...}
}5. 高级配置
5.1 监听器顺序控制
EventListener
Order(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
public void handleEventFirst(MyEvent event) {// 最先执行
}5.2 异步事件处理
Configuration
EnableAsync
public class AsyncConfig implements AsyncConfigurer {Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.initialize();return executor;}
}EventListener
Async
public void asyncHandleEvent(MyEvent event) {// 异步执行
}5.3 条件过滤
EventListener(condition #event.orderId.startsWith(VIP))
public void handleVipOrder(OrderCreateEvent event) {// 只处理VIP订单
}6.详细使用场景 场景1应用启动时缓存预热系统事件监听
需求描述 在应用启动完成后自动加载热门商品数据到Redis缓存提升接口响应速度。
Component
public class CacheWarmUpListener {private final ProductService productService;private final RedisTemplateString, Product redisTemplate;Autowiredpublic CacheWarmUpListener(ProductService productService, RedisTemplateString, Product redisTemplate) {this.productService productService;this.redisTemplate redisTemplate;}EventListener(ApplicationReadyEvent.class)public void warmUpCache() {ListProduct hotProducts productService.getTop100HotProducts();hotProducts.forEach(product - redisTemplate.opsForValue().set(product: product.getId(), product));System.out.println( 已预热 hotProducts.size() 条商品数据到Redis );}
}关键点说明
使用ApplicationReadyEvent而非ApplicationStartedEvent确保数据库连接等基础设施已就绪通过构造函数注入依赖避免字段注入的循环依赖问题预热数据量较大时建议采用分页异步加载 场景2订单创建后发送多平台通知自定义事件
需求描述 当订单创建成功后需要同时发送短信通知用户、邮件通知客服、更新ERP系统库存。
步骤1定义自定义事件
public class OrderCreatedEvent extends ApplicationEvent {private final Order order;public OrderCreatedEvent(Object source, Order order) {super(source);this.order order;}public Order getOrder() {return order;}
}步骤2在Service中发布事件
Service
public class OrderService {private final ApplicationEventPublisher eventPublisher;Autowiredpublic OrderService(ApplicationEventPublisher eventPublisher) {this.eventPublisher eventPublisher;}Transactionalpublic Order createOrder(OrderCreateRequest request) {Order newOrder // 创建订单的数据库操作...eventPublisher.publishEvent(new OrderCreatedEvent(this, newOrder));return newOrder;}
}步骤3多监听器处理事件
Component
public class OrderNotificationListener {// 短信通知最高优先级EventListenerOrder(Ordered.HIGHEST_PRECEDENCE)public void sendSms(OrderCreatedEvent event) {Order order event.getOrder();SmsService.send(order.getUserPhone(), 您的订单# order.getId() 已创建金额 order.getAmount());}// 邮件通知异步处理AsyncEventListenerpublic void sendEmail(OrderCreatedEvent event) {Order order event.getOrder();EmailTemplate template EmailTemplate.buildOrderConfirm(order);EmailService.send(template);}// ERP系统库存更新条件过滤EventListener(condition #event.order.items.?[isPhysicalProduct].size() 0)public void updateErpInventory(OrderCreatedEvent event) {ERPInventoryService.updateStock(event.getOrder().getItems());}
}配置异步支持
Configuration
EnableAsync
public class AsyncConfig {Bean(name notificationTaskExecutor)public Executor taskExecutor() {ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(100);executor.setThreadNamePrefix(Notification-);executor.initialize();return executor;}
}优势
解耦核心业务与通知逻辑通过Order控制短信优先于邮件发送使用Async避免邮件发送阻塞主线程条件表达式跳过虚拟商品库存更新 场景3全局请求耗时统计ServletRequestListener
需求描述 统计所有API请求的处理时间识别慢接口。
Component
public class RequestMetricsListener implements ServletRequestListener {private static final ThreadLocalLong startTimeHolder new ThreadLocal();Overridepublic void requestInitialized(ServletRequestEvent sre) {startTimeHolder.set(System.currentTimeMillis());}Overridepublic void requestDestroyed(ServletRequestEvent sre) {long startTime startTimeHolder.get();long duration System.currentTimeMillis() - startTime;HttpServletRequest request (HttpServletRequest) sre.getServletRequest();String endpoint request.getRequestURI();String method request.getMethod();MetricsService.recordRequestMetrics(endpoint, method, duration);// 慢请求预警if(duration 3000) {AlarmService.notifySlowRequest(endpoint, method, duration);}startTimeHolder.remove();}
}注册监听器
Bean
public ServletListenerRegistrationBeanRequestMetricsListener metricsListener() {return new ServletListenerRegistrationBean(new RequestMetricsListener());
}统计结果示例
GET /api/products 平均耗时 45ms | 95分位 120ms
POST /api/orders 平均耗时 250ms | 最大耗时 3200ms需优化场景4应用优雅停机ContextClosedEvent
需求描述 在应用关闭时确保完成1停止接收新请求 2等待进行中的任务完成 3释放资源。
Component
public class GracefulShutdownListener implements ApplicationListenerContextClosedEvent {private final ThreadPoolTaskExecutor taskExecutor;private final DataSource dataSource;Autowiredpublic GracefulShutdownListener(ThreadPoolTaskExecutor taskExecutor, DataSource dataSource) {this.taskExecutor taskExecutor;this.dataSource dataSource;}Overridepublic void onApplicationEvent(ContextClosedEvent event) {// 1. 关闭线程池shutdownExecutor(taskExecutor);// 2. 关闭数据库连接池if(dataSource instanceof HikariDataSource) {((HikariDataSource) dataSource).close();}// 3. 其他清理工作...System.out.println( 资源释放完成应用安全退出 );}private void shutdownExecutor(ExecutorService executor) {executor.shutdown();try {if(!executor.awaitTermination(30, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();}}
}停机流程
收到SIGTERM信号关闭新请求入口等待30秒处理进行中请求强制关闭剩余任务释放数据库连接池应用退出 场景5分布式锁异常恢复
需求描述 当获取Redis分布式锁失败时触发重试机制并记录竞争情况。
自定义事件
public class LockAcquireFailedEvent extends ApplicationEvent {private final String lockKey;private final int retryCount;public LockAcquireFailedEvent(Object source, String lockKey, int retryCount) {super(source);this.lockKey lockKey;this.retryCount retryCount;}// getters...
}事件发布
public class DistributedLock {private final ApplicationEventPublisher eventPublisher;public boolean tryLock(String key, int maxRetries) {int attempts 0;while(attempts maxRetries) {if(RedisClient.acquireLock(key)) {return true;}attempts;eventPublisher.publishEvent(new LockAcquireFailedEvent(this, key, attempts));Thread.sleep(100 * attempts);}return false;}
}监听处理
Component
public class LockFailureHandler {private static final MapString, AtomicInteger LOCK_CONTENTION new ConcurrentHashMap();EventListenerpublic void handleLockFailure(LockAcquireFailedEvent event) {String lockKey event.getLockKey();LOCK_CONTENTION.computeIfAbsent(lockKey, k - new AtomicInteger(0)).incrementAndGet();// 竞争激烈时动态调整策略if(event.getRetryCount() 3) {adjustBackoffStrategy(lockKey);}}Scheduled(fixedRate 10_000)public void reportContention() {LOCK_CONTENTION.forEach((key, count) - MetricsService.recordLockContention(key, count.get()));}private void adjustBackoffStrategy(String key) {// 动态增加等待时间或告警}
}监控面板显示
订单库存锁竞争次数142次/分钟 → 建议拆分锁粒度
优惠券发放锁竞争23次/分钟 → 正常范围最佳实践总结 事件选择原则 系统生命周期优先使用ApplicationReadyEvent而非ContextRefreshedEvent业务事件根据领域模型设计细粒度事件 性能优化 耗时操作使用Async线程池高频事件考虑批量处理 错误处理 EventListener
public void handleEvent(MyEvent event) {try {// 业务逻辑} catch (Exception e) {ErrorTracker.track(e);// 决定是否重新抛出}
}测试策略 SpringBootTest
class OrderEventTest {Autowiredprivate ApplicationEventPublisher publisher;Testvoid testOrderNotification() {Order mockOrder createTestOrder();publisher.publishEvent(new OrderCreatedEvent(this, mockOrder));// 验证短信、邮件发送记录}
}7.总结
通过以上场景可以看出Spring Boot监听器能优雅地实现
系统层的资源生命周期管理业务层的事件驱动架构运维层的监控预警机制架构层的解耦与扩展
实际开发中应根据业务复杂度选择合适的事件策略平衡灵活性与维护成本。