SpringEvent介绍
实现Spring事件机制主要有4个类:
ApplicationEvent:事件,每个实现类表示一类事件,可携带数据。
ApplicationListener:事件监听器,用于接收事件处理时间。
ApplicationEventMulticaster:事件管理者,用于事件监听器的注册和事件的广播。
ApplicationEventPublisher:事件发布者,委托ApplicationEventMulticaster完成事件发布
实际应用
当用户注册完成时能够给用户的邮箱发送一封邮件提醒
1.声明一个事件实体继承ApplicationEvent类
public class RegistryEvent extends ApplicationEvent { /** * Create a new {@code ApplicationEvent}. * * @param source the object on which the event initially occurred or with * which the event is associated (never {@code null}) */ public RegistryEvent(Object source) { super(source); } }
2.声明事件发布业务
@Component public class ApplicationSendEventService { @Resource private ApplicationEventPublisher applicationEventPublisher; public void sendRegistryEvent(Object message){ applicationEventPublisher.publishEvent(new RegistryEvent(message)); } }
3.定义监听器监听事件
@Component @Slf4j public class RegistryEventListener { @Resource private ConstantConfig constant; @Resource private JavaMailSender javaMailSender; @EventListener(value = RegistryEvent.class) public void registryEventSendMailHandler(RegistryEvent registryEvent) { SysUser sysUser = (SysUser) registryEvent.getSource(); String recipient = sysUser.getUsername(); String mailContent = "您的邮箱在" + DateUtil.format(new Date(), "yyyy-MM-dd") + "在平台注册成功,如非本人操作请进入平台进行申诉!"; EmailUtil.sendMail(constant.getMailSender(), recipient, javaMailSender, REGISTRY_SUCCESS_MAIL_SUBJECT, mailContent); log.info("已向用户{}发送注册成功提示邮箱!", recipient); } @EventListener(value = RegistryEvent.class) public void registryEventInitAccountHandler(RegistryEvent registryEvent) { log.info("测试是否能够进行两次监听") } }
问题
使用事件发布机制时,如果事件发布方和事件监听放需要进行事务管理是没办法的,比如事件发布方对数据库进行了更新,然后事件监听放也对数据库进行更新,如果这两个操作是相互关联的,那么监听方发生错误时,应该发布方执行的数据库操作要回退。这种要想保证事务是没办法的,只能借鉴SpringCloud中的seata组件的思想,二阶段提交,但是这个太难了,不实现了。而且这种事件发布机制本身就不应该存在数据相互关联(个人看法)