ApplicationEventMulticaster管理很多个ApplicationListener对象,并将事件发布给这些监听器。
事件派发器
public interface ApplicationEventMulticaster{
void addApplicationListener(ApplicationListener<?> listener);
void addApplicationListenerBean(String listenerBeanName);
void removeApplicationListener(ApplicationListener<?> listener);
void removeApplicationListenerBean(String listenerBeanName);
void removeAllListeners();
void multicastEvent(ApplicationEvent event);
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}
ApplicationListener 事件监听器,也就是观察者。
当监听的事件发生后onApplicationEvent()方法会被执行。
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
流程
- 在启动Web容器时,自动装配Spring applicationContext.xml的配置信息。
ClassPathXmlApplicationContext的构造器会执行refresh()方法 - AbstractApplicationContext类下,
public void refresh() throws BeansException, IllegalStateException {
// 初始化ApplicationEventMulticaster
initApplicationEventMulticaster();
registerListeners();
finishRefresh();
}
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 先去容器中找有没有id=“applicationEventMulticaster”的组件
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
}else {
// 如果没有,new SimpleApplicationEventMulticaster(beanFactory)
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
// 加入到容器中
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
protected void finishRefresh() {
// 发布事件
publishEvent(new ContextRefreshedEvent(this));
}
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
}
- SimpleApplicationEventMulticaster类下,
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
//异步派发
executor.execute(() -> invokeListener(listener, event));
}else {
//同步的方式
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}catch (Throwable err) {
errorHandler.handleError(err);
}
}else {
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 执行监听事件
listener.onApplicationEvent(event);
}catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass().getName())) {
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}else {
throw ex;
}
}
}
ContextRefreshedEvent
ApplicationContext 被初始化或刷新时,该事件被发布。
此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用。
public class ContextRefreshedEvent extends ApplicationContextEvent {
public ContextRefreshedEvent(ApplicationContext source) {
super(source);
}
}
public abstract class ApplicationContextEvent extends ApplicationEvent {}
public abstract class ApplicationEvent extends EventObject{}
public class EventObject implements java.io.Serializable {}
ContextStartedEvent
当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。
ContextStoppedEvent
当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。
ContextClosedEvent
当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。
RequestHandledEvent
这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。
只能应用于使用DispatcherServlet的Web应用。
在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。
自定义ApplicationLisener
使用ApplicationListener监听使方法仅在项目启动时执行一次
public class NotifyEvent extends ApplicationEvent {
private String email;
private String content;
public NotifyEvent(Object source) {
super(source);
}
public NotifyEvent(Object source, String email, String content) {
super(source);
this.email = email;
this.content = content;
}
}
public class RSAKeyInitListener implements ApplicationListener<ContextRefreshedEvent> {
}
//如果入参是ApplicationEvent,则每当容器内发生任何事件时,此方法都会被触发
//如果入参是NotifyEvent,则只有容器内发生如果入参是NotifyEvent事件时,此方法才会被触发
@Component
public class MyApplicationListener implements ApplicationListener<NotifyEvent> {
@Override
public void onApplicationEvent(NotifyEvent event) {
System.out.println("MyApplicationListener");
System.out.println("邮件地址:" + event.getEmail());
System.out.println("邮件内容:" + event.getContent());
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class ListenerTest {
@Autowired
private WebApplicationContext webApplicationContext;
@Test
public void testListener() {
NotifyEvent event = new NotifyEvent("object", "abc@qq.com", "This is the content");
webApplicationContext.publishEvent(event);
}
}