Spring事件机制通过ApplicationEvent和ApplicationListener实现解耦,自定义事件需继承ApplicationEvent,发布用ApplicationEventPublisher,监听支持@EventListener(推荐)或ApplicationListener接口,可配置顺序与异步处理。

在 Spring 中,ApplicationEvent 和 ApplicationListener 是实现轻量级事件驱动模型的核心机制,适合解耦组件、响应系统内状态变化(如用户注册成功后发邮件、订单创建后更新库存等)。
自定义事件:继承 ApplicationEvent
Spring 的事件必须是 ApplicationEvent 的子类。推荐将业务数据封装进事件对象中,并提供构造方法和 getter:
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 一般传入当前发布事件的 Bean(如 this),Spring 会自动注入上下文信息;也可传 null,但不推荐——丢失来源不利于调试和扩展。
发布事件:使用 ApplicationEventPublisher
任意 Spring 管理的 Bean 都可通过依赖注入 ApplicationEventPublisher 来发布事件:
立即学习“Java免费学习笔记(深入)”;
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void registerUser(String username, String email) {
// 保存用户逻辑...
System.out.println("User saved: " + username);
// 发布事件
eventPublisher.publishEvent(
new UserRegisteredEvent(this, username, email)
);
}
}
发布是同步的(默认行为),即监听器执行完,发布方法才返回。如需异步,需配合 @Async 和线程池配置,且监听器方法需加 @EventListener 或实现 ApplicationListener 接口并确保其 Bean 支持异步。
监听事件:两种方式任选其一
方式一:用 @EventListener 注解(推荐)
简洁、支持条件过滤、可监听多个事件、支持泛型推导:
@Component
public class EmailNotificationListener {
@EventListener
public void handleUserRegistered(UserRegisteredEvent event) {
System.out.println("Sending welcome email to " + event.getEmail());
// 发送邮件逻辑...
}
// 可监听多个事件类型
@EventListener({UserRegisteredEvent.class, UserUpdatedEvent.class})
public void onUserChange(ApplicationEvent event) {
// 统一处理...
}
// 条件监听(SpEL 表达式)
@EventListener(condition = "#event.username.length() > 3")
public void handleLongUsername(UserRegisteredEvent event) {
// 仅当用户名长度 > 3 时触发
}
}
方式二:实现 ApplicationListener 接口
更传统,适合老项目或需要严格类型控制的场景:
@Component
public class SmsNotificationListener implements ApplicationListener<UserRegisteredEvent> {
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
System.out.println("Sending SMS to " + event.getPhone());
// 发短信逻辑...
}
}
注意:该接口不支持 SpEL 条件、泛型多事件监听等高级特性,且泛型擦除后若监听父类事件,需手动判断类型。
事件传播与顺序控制
多个监听器默认按注册顺序执行(即 Bean 创建顺序),无固定优先级。如需控制顺序:
- 实现
Ordered接口或添加@Order注解(值越小越先执行) - 使用
@EventListener时,可在方法上加@Order(10) - 避免在监听器中抛出未捕获异常——它会中断后续监听器执行(同步模式下)
若希望异常不影响其他监听器,可用 try-catch 包裹业务逻辑,或改用异步监听(需配置 TaskExecutor 并启用 @EnableAsync)。



















