观察者模式:ApplicationLisener

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);
}

流程

  1. 在启动Web容器时,自动装配Spring applicationContext.xml的配置信息。
    ClassPathXmlApplicationContext的构造器会执行refresh()方法
  2. 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);
	}
}
  1. 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);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值