首先来个demo看看怎么使用:
定义事件:
public class EmailEvent extends ApplicationEvent{
private String address;
private String text;
public EmailEvent(Object source, String address, String text){
super(source);
this.address = address;
this.text = text;
}
public EmailEvent(Object source) {
super(source);
}
//......address和text的setter、getter
}
定义监听:
@Component
public class EmailNotifier implements ApplicationListener{
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof EmailEvent) {
EmailEvent emailEvent = (EmailEvent)event;
System.out.println("邮件地址:" + emailEvent.getAddress());
System.our.println("邮件内容:" + emailEvent.getText());
} else {
}
}
}
测试:
public class SpringTest {
public static void main(String args[]){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//创建一个ApplicationEvent对象
EmailEvent event = new EmailEvent("hello","abc@163.com","This is a test");
//主动触发该事件
context.publishEvent(event);
}
}
看看结果:
邮件地址:abc@163.com
邮件内容:This is a test
通过上面的案例可以知道,我们需要先定义一个事件类继承ApplicationEvent,然后定义一个监听实现ApplicationListener,并且要把监听加入到spring管理中(可以使用注解方式或者xml方式),最后使用的时候只要实例化事件,然后发布事件,那么自然能监听到事件。
源码分析
找到spring源码路径ClassPathXmlApplicationContext->AbstractApplicationContext的refresh方法->initApplicationEventMulticaster方法:
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
/**
* 判断容器中是否存在bdName为applicationEventMulticaster的bd
* 也就是自定义的事件监听多路广播器,必须实现ApplicationEventMulticaster接口
*/
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
/**
* 如果没有,则默认采用SimpleApplicationEventMulticaster
*/
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
这里就是初始化ApplicationEventMulticaster。
接下来我们看看AbstractApplicationContext的refresh方法->finishRefresh方法:
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
//初始化生命周期管理器LifecycleProcessor
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
//启动所有实现了Lifecycle接口的bean
getLifecycleProcessor().onRefresh();
// Publish the final event.
//发布刷新完成事件
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
再进入publishEvent(new ContextRefreshedEvent(this)):
protected void publishEvent(Object event, ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
// Decorate event as an ApplicationEvent if necessary
// 将事件封装为ApplicationEvent
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<Object>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
//使用事件广播器,广播时间
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
// 通过parent发布时间
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
接下来看看multicastEvent(applicationEvent, eventType)方法:
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
上面就是遍历ApplicationListener,然后执行invokeListener(listener, event),那么接下来我们看看invokeListener:
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
listener.onApplicationEvent(event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || msg.startsWith(event.getClass().getName())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
}
这里就知道了最后是调用了listener.onApplicationEvent(event)方法,这就是为什么我们实现ApplicationListener 接口,重写onApplicationEvent方法就能监听到事件了。