spring applicationevent 机制提供轻量松耦合的jvm内事件通知,支持自定义事件继承applicationevent、通过applicationeventpublisher发布、@eventlistener监听,可异步执行或事务提交后触发。

Spring 的 ApplicationEvent 机制提供了一种轻量、松耦合的内部事件通知方式,适合在同一个 JVM 内不同组件之间传递状态变化或业务信号(比如用户注册成功后发邮件、订单创建后更新库存)。
定义自定义事件
继承 ApplicationEvent,构造函数中传入事件源(通常是触发事件的对象):
public class UserRegisteredEvent extends ApplicationEvent {
private final String username;
private final String email;
public UserRegisteredEvent(Object source, String username, String email) {
super(source);
this.username = username;
this.email = email;
}
// getter...
}
注意:事件类本身不需实现任何接口,也不用加注解;source 一般传 this 或业务对象(如 new UserRegisteredEvent(user, user.getName(), user.getEmail()))。
发布事件
在业务逻辑中通过 ApplicationEventPublisher 发布事件。推荐注入该接口(Spring 自动装配):
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void registerUser(String name, String email) {
// 保存用户...
User user = new User(name, email);
userRepository.save(user);
// 发布事件
eventPublisher.publishEvent(new UserRegisteredEvent(this, name, email));
}
}
- 事件默认是同步执行的(即发布后立刻调用监听器,当前线程阻塞直到监听器完成)
- 如果需要异步,可配合
@Async使用(需开启异步支持:@EnableAsync) - 不建议在事务方法中直接发布“影响下游事务”的事件,除非明确处理事务传播行为(如用
TransactionSynchronizationManager注册事务提交后回调)
监听事件(响应事件)
有三种常用方式,推荐使用基于注解的方式:
- @EventListener:最简洁,支持条件过滤和泛型推导
- 实现 ApplicationListener 接口:老式写法,类型由泛型指定
- 重写 onApplicationEvent 方法:适用于监听多种事件,但需手动 instanceof 判断
示例(推荐):
@Component
public class UserRegistrationListener {
@EventListener
public void handleUserRegistered(UserRegisteredEvent event) {
System.out.println("发送欢迎邮件给:" + event.getEmail());
// 调用邮件服务...
}
// 可选:按条件监听(SpEL 表达式)
@EventListener(condition = "#event.username.length() > 3")
public void handleLongUsername(UserRegisteredEvent event) {
System.out.println("用户名较长,记录日志");
}
}
进阶:异步监听与事务感知
若监听逻辑耗时(如发短信、调外部 API),应异步执行:
@Component
public class AsyncUserRegistrationListener {
@Async
@EventListener
public void sendWelcomeSms(UserRegisteredEvent event) {
// 这个方法将在独立线程中执行
smsService.send(event.getPhone(), "欢迎注册!");
}
}
若需确保监听器只在事务成功提交后执行(避免事务回滚导致事件误处理),可用:
@EventListener
public void afterCommit(UserRegisteredEvent event) {
if (TransactionSynchronizationManager.isActualTransactionActive()) {
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
// 这里执行真正要做的事
notifyThirdParty(event.getUsername());
}
}
);
}
}
不复杂但容易忽略。用好 ApplicationEvent,能让业务逻辑更清晰、扩展性更强。









