ApplicationContext 事件发布与监听机制详解
ApplicationContext 事件发布与监听机制详解
ApplicationContext 接口是 Spring 框架的核心容器接口,它提供了事件发布与监听机制,允许应用程序组件之间通过事件进行松耦合通信。这种机制基于观察者模式,实现了发布-订阅模型。
核心概念
- 事件(ApplicationEvent): 所有事件类的基类,Spring 提供了多种内置事件
- 事件发布者(ApplicationEventPublisher): 发布事件的接口,ApplicationContext 实现了此接口
- 事件监听器(ApplicationListener): 监听特定事件的接口
主要方法
1. 事件发布相关方法
publishEvent(Object event)
: 发布事件(在 Spring 4.2+ 中,可以直接发布任何对象作为事件)publishEvent(ApplicationEvent event)
: 发布标准 ApplicationEvent 事件
2. 事件监听相关方法
- 通过实现
ApplicationListener<E extends ApplicationEvent>
接口 - 或使用
@EventListener
注解(Spring 4.2+ 推荐方式)
内置事件类型
Spring 提供了一些内置事件:
- ContextRefreshedEvent: ApplicationContext 初始化或刷新时触发
- ContextStartedEvent: ApplicationContext 启动时触发
- ContextStoppedEvent: ApplicationContext 停止时触发
- ContextClosedEvent: ApplicationContext 关闭时触发
- RequestHandledEvent: Web 请求处理完成时触发(仅适用于 Web 应用)
实现方式
方式1:实现 ApplicationListener 接口
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;@Component
public class MyContextRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {System.out.println("Context refreshed event received!");}
}
方式2:使用 @EventListener 注解(推荐)
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;@Component
public class MyEventListener {@EventListenerpublic void handleContextRefresh(ContextRefreshedEvent event) {System.out.println("Context refreshed event handled via @EventListener!");}// 可以监听多个事件类型@EventListener({ContextStartedEvent.class, ContextStoppedEvent.class})public void handleMultipleEvents(ApplicationEvent event) {if (event instanceof ContextStartedEvent) {System.out.println("Context started event received");} else if (event instanceof ContextStoppedEvent) {System.out.println("Context stopped event received");}}
}
方式3:自定义事件
- 定义自定义事件类:
import org.springframework.context.ApplicationEvent;public class CustomEvent extends ApplicationEvent {private String message;public CustomEvent(Object source, String message) {super(source);this.message = message;}public String getMessage() {return message;}
}
- 创建事件发布者:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;@Service
public class EventPublisherService {@Autowiredprivate ApplicationEventPublisher eventPublisher;public void publishCustomEvent(String message) {System.out.println("Publishing custom event...");CustomEvent event = new CustomEvent(this, message);eventPublisher.publishEvent(event);}
}
- 创建事件监听器:
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;@Component
public class CustomEventListener {@EventListenerpublic void handleCustomEvent(CustomEvent event) {System.out.println("Received custom event - Message: " + event.getMessage());}
}
完整示例
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;@SpringBootApplication
public class EventApplication {public static void main(String[] args) {SpringApplication.run(EventApplication.class, args);}
}// 自定义事件
class OrderCreatedEvent {private final String orderId;public OrderCreatedEvent(String orderId) {this.orderId = orderId;}public String getOrderId() {return orderId;}
}// 事件发布服务
@Component
class OrderService {private final ApplicationEventPublisher eventPublisher;public OrderService(ApplicationEventPublisher eventPublisher) {this.eventPublisher = eventPublisher;}public void createOrder(String orderId) {System.out.println("Creating order: " + orderId);// 业务逻辑...eventPublisher.publishEvent(new OrderCreatedEvent(orderId));}
}// 方式1:实现 ApplicationListener 接口
@Component
class OrderNotificationListener implements ApplicationListener<OrderCreatedEvent> {@Overridepublic void onApplicationEvent(OrderCreatedEvent event) {System.out.println("Sending notification for order: " + event.getOrderId());}
}// 方式2:使用 @EventListener 注解
@Component
class OrderInventoryListener {@EventListenerpublic void updateInventory(OrderCreatedEvent event) {System.out.println("Updating inventory for order: " + event.getOrderId());}
}// 监听内置事件
@Component
class ContextStartupListener {@EventListenerpublic void onContextRefreshed(ContextRefreshedEvent event) {System.out.println("Application context has been refreshed!");}
}
异步事件处理
要使事件监听异步执行,可以添加 @Async
注解:
- 首先在配置类上启用异步支持:
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;@Configuration
@EnableAsync
public class AsyncConfig {
}
- 然后在监听方法上添加
@Async
:
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;@Component
public class AsyncEventListener {@Async@EventListenerpublic void handleAsyncEvent(OrderCreatedEvent event) {System.out.println("Processing event asynchronously for order: " + event.getOrderId());try {Thread.sleep(2000); // 模拟耗时操作} catch (InterruptedException e) {Thread.currentThread().interrupt();}System.out.println("Async processing completed for order: " + event.getOrderId());}
}
事件传播顺序
如果需要控制多个监听器的执行顺序,可以使用 @Order
注解:
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;@Component
@Order(1)
class FirstOrderListener {@EventListenerpublic void handleFirst(OrderCreatedEvent event) {System.out.println("First listener for order: " + event.getOrderId());}
}@Component
@Order(2)
class SecondOrderListener {@EventListenerpublic void handleSecond(OrderCreatedEvent event) {System.out.println("Second listener for order: " + event.getOrderId());}
}
总结
ApplicationContext 的事件机制提供了强大的组件间解耦通信能力:
- 松耦合:发布者和监听者不需要知道彼此的存在
- 灵活性:可以轻松添加或移除监听器而不影响现有代码
- 可扩展性:支持自定义事件类型
- 异步支持:通过
@Async
实现非阻塞事件处理 - 顺序控制:通过
@Order
控制监听器执行顺序
这种机制特别适用于实现跨模块的通知、日志记录、审计跟踪、缓存失效等场景。