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

app开发制作网站平台网络建站优化科技

app开发制作网站平台,网络建站优化科技,单词优化和整站优化,海口网站建设公司Spring Boot 监听器(Listeners)详细教程 目录 Spring Boot 监听器概述监听器核心概念最佳使用场景实现步骤高级配置详细使用场景总结 1. Spring Boot 监听器概述 Spring Boot 监听器(Listeners)基于 Spring Framework 的事件机制…

Spring Boot 监听器(Listeners)详细教程


目录

  1. Spring Boot 监听器概述
  2. 监听器核心概念
  3. 最佳使用场景
  4. 实现步骤
  5. 高级配置
  6. 详细使用场景
  7. 总结

1. Spring Boot 监听器概述

Spring Boot 监听器(Listeners)基于 Spring Framework 的事件机制(ApplicationEventApplicationListener),用于在应用生命周期或自定义事件触发时执行特定逻辑。它们提供了一种松耦合的方式响应应用状态变化,常用于初始化资源、监控应用状态、执行异步任务等。

2. 核心概念

2.1 事件类型

  • 内置系统事件
    • ContextRefreshedEvent:ApplicationContext初始化或刷新时触发
    • ContextStartedEvent:ApplicationContext启动后触发
    • ContextStoppedEvent:ApplicationContext停止后触发
    • ContextClosedEvent:ApplicationContext关闭后触发
    • ApplicationStartedEvent:Spring Boot应用启动后触发
    • ApplicationReadyEvent:应用准备就绪时触发(推荐在此执行启动逻辑)
    • ApplicationFailedEvent:启动失败时触发
  • 自定义事件:继承ApplicationEvent创建特定业务事件

2.2 监听器类型

  • 接口实现:实现ApplicationListener<EventType>
  • 注解驱动:使用@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 ApplicationListener<ApplicationReadyEvent> {@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 RedisTemplate<String, Product> redisTemplate;@Autowiredpublic CacheWarmUpListener(ProductService productService, RedisTemplate<String, Product> redisTemplate) {this.productService = productService;this.redisTemplate = redisTemplate;}@EventListener(ApplicationReadyEvent.class)public void warmUpCache() {List<Product> 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 {// 短信通知(最高优先级)@EventListener@Order(Ordered.HIGHEST_PRECEDENCE)public void sendSms(OrderCreatedEvent event) {Order order = event.getOrder();SmsService.send(order.getUserPhone(), "您的订单#" + order.getId() + "已创建,金额:" + order.getAmount());}// 邮件通知(异步处理)@Async@EventListenerpublic 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 ThreadLocal<Long> 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 ServletListenerRegistrationBean<RequestMetricsListener> 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 ApplicationListener<ContextClosedEvent> {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();}}
}

停机流程

  1. 收到SIGTERM信号
  2. 关闭新请求入口
  3. 等待30秒处理进行中请求
  4. 强制关闭剩余任务
  5. 释放数据库连接池
  6. 应用退出

场景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 Map<String, 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次/分钟 → 正常范围

最佳实践总结

  1. 事件选择原则

    • 系统生命周期:优先使用ApplicationReadyEvent而非ContextRefreshedEvent
    • 业务事件:根据领域模型设计细粒度事件
  2. 性能优化

    • 耗时操作使用@Async+线程池
    • 高频事件考虑批量处理
  3. 错误处理

    @EventListener
    public void handleEvent(MyEvent event) {try {// 业务逻辑} catch (Exception e) {ErrorTracker.track(e);// 决定是否重新抛出}
    }
    
  4. 测试策略

    @SpringBootTest
    class OrderEventTest {@Autowiredprivate ApplicationEventPublisher publisher;@Testvoid testOrderNotification() {Order mockOrder = createTestOrder();publisher.publishEvent(new OrderCreatedEvent(this, mockOrder));// 验证短信、邮件发送记录}
    }
    

7.总结

通过以上场景可以看出,Spring Boot监听器能优雅地实现:

  • 系统层的资源生命周期管理
  • 业务层的事件驱动架构
  • 运维层的监控预警机制
  • 架构层的解耦与扩展

实际开发中应根据业务复杂度选择合适的事件策略,平衡灵活性与维护成本。

http://www.dtcms.com/wzjs/221416.html

相关文章:

  • 陕西广告公司网站建设百度股市行情上证指数
  • 网站建设的售后服务怎么写收录好的网站有哪些
  • 土木毕业设计代做网站安卓优化大师新版
  • 网站建设精英seo网络推广到底是做什么的
  • 新疆建设兵团管理局网站优化网站标题
  • 山东省建设发展研究院网站百度seo排名曝光行者seo
  • 成都装修公司十大排名网站建设优化推广系统
  • 一个网站多少钱?郭生b如何优化网站
  • 手机怎么进入国外网站重庆seo网站排名
  • 毕业论文网站设计与建设关键词排名优化易下拉软件
  • 微信采集wordpressseo排名优化工具推荐
  • 用macbook做网站开发网络营销技能大赛优秀作品
  • 商务网站建设联系方式百度seo关键词排名 s
  • 兼职做任务的网站怎样在百度上打广告
  • 国际b2c电商平台有哪些站长工具seo综合查询怎么关闭
  • bluehost 网站后台杭州网站优化咨询
  • 美食网站的设计与制作代码泰州seo
  • 小程序源码怎么使用seo二级目录
  • 2345网址大全设主页访问app优化推广
  • 妇科医院网站建设怎么做免费下载百度并安装
  • 顺德定制网站建设seo咨询邵阳
  • html5网站图标关键词优化一年多少钱
  • 商务网站建设哪家好如何制作一个网址
  • 做网站1008做网站 - 百度网站建立的步骤
  • 哪个网站免费建站最好博客可以做seo吗
  • 建设官网流程自动优化app
  • 环卫公厕建设门户网站访谈如何制作小程序
  • 福彩hao123网址导航如何做seo整站优化
  • 政府网站格式建一个企业网站多少钱
  • 西宁做网站的有吗yandere搜索引擎入口