前言
先说一下需求。如果用户注册了之后,想发送短信或者邮箱提醒注册成功。又因为用户跟发送信息是两个独立的模块,不想过多耦合。这时候该怎么做?
一般来说可以加一个消息中间件,比如 kafka,这也是最常见的一种方法,高性能。除了这个不加其他技术栈,就用 spring 解决的?
那就是事件驱动ApplicationEvent
正文
ApplicationEvent
是 Spring 框架中用于实现事件驱动编程的关键组件之一。让我详细解释一下:
什么是 ApplicationEvent
ApplicationEvent
是 Spring 框架中的一个类,用于表示应用程序中的事件。- 事件可以是应用程序内部的状态变化、用户操作、外部系统通信等。
- 通过发布和监听事件,我们可以
实现松散耦合
的组件之间的通信。
如何使用 ApplicationEvent
- 创建自定义事件类:可以扩展
ApplicationEvent
类来创建自己的事件。例如,用户注册事件、消息发送事件等。 - 发布事件:在适当的时机,可以使用
ApplicationEventPublisher
接口发布事件。 - 监听事件:通过实现事件监听器,可以在事件发生时执行相应的操作。
示例:用户注册事件
-
首先,我们创建一个自定义事件类
UserRegistrationEvent
继承自ApplicationEvent
:javapublic class UserRegistrationEvent extends ApplicationEvent { private String username; public UserRegistrationEvent(Object source, String username) { super(source); this.username = username; } public String getUsername() { return username; } }
-
然后,我们创建一个服务类
UserService
,用于处理用户注册逻辑并发布事件:java@Service public class UserService { @Autowired private ApplicationEventPublisher eventPublisher; public void registerUser(String username) { // ... 用户注册逻辑 ... // 发布 UserRegistrationEvent 事件 eventPublisher.publishEvent(new UserRegistrationEvent(this, username)); } }
-
再创建消息服务类 Message,用于处理消息发送
java@Service public class MessageService { private static Logger logger = LoggerFactory.getLogger(MessageService.class); public void sendMessage(String username) { logger.info("MessageService.sendMessage():{}",username); } }
-
最后,我们创建一个事件监听器
UserRegistrationListener
,以便在用户注册时执行相应的操作:java@Component public class UserRegistrationListener { private Logger logger = LoggerFactory.getLogger(getClass()); private ScheduledExecutorService executorService = null; @Autowired private MessageService messageService; /** * 事件处理监听 * @param event */ @EventListener public void handleUserRegistration(UserRegistrationEvent event) { logger.info("监听到一条新的信息:{}", event.getUsername()); // 延迟一段时间后再创建 if (executorService == null) { executorService = Executors.newScheduledThreadPool(1); } // 延迟一段时间后再执行,防止流程流转时数据还没更新到数据库 long delayInSeconds = 1; // 延迟1秒 executorService.schedule(() -> { // 执行事件 messageService.sendMessage(event.getUsername()); }, delayInSeconds, TimeUnit.SECONDS); } @PreDestroy public void destroy() { // 执行清理操作 executorService.shutdown(); } }
-
测试
java@RestController @RequestMapping("/user/test") public class UserController { private static Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private UserService userService; @PostMapping public CommonResult userRegistration() { String username = "user1"; logger.info("注册用户:{}" , username); userService.registerUser(username); return CommonResult.ok(); } }
总结
- 使用
ApplicationEvent
,可以构建松散耦合且可扩展的应用程序。 - 通过自定义事件、事件发布者和事件监听器,您可以实现事件驱动的编程模型,提高应用程序的灵活性和可维护性。