一、监听器相关接口
1、ApplicationEventPublisher容器的事件发布者
//该接口规范了发布事件的基本功能
public interface ApplicationEventPublisher {
/**
* 发布事件
*/
void publishEvent(ApplicationEvent event);
/**
* 发布事件
*/
void publishEvent(Object event);
}
2、ApplicationEvent事件基类
//不同的事件继承自这个类 通过instanceof运算符来区分到底产生的是什么事件
public abstract class ApplicationEvent extends EventObject {
...
}
3、ApplicationEventMulticaster事件传播者
//该接口定义了一些监听器的增删改的方法可以参考下jdk的java.util.Observable很相像
public interface ApplicationEventMulticaster {
...
}
4、ApplicationListener事件监听器接口
//实现了该接口 就可以监听容器产生的相关事件了
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* 当容器中发布事件时,其实就是通过ApplicationEventMulticaster的实现类遍历监听器调用的该方法
*/
void onApplicationEvent(E event);
}
5、事件类型
二、容器中监听器相关接口的实现
1、ApplicationEventPublisher事件发布者ApplicationContext
spring在AbstractApplicationContext中实现了ApplicationEventPublisher相关功能
通过下面的代码可以看出其实ApplicationEventPublisher中的事件最终是由ApplicationEventMulticaster
来实现事件发布的
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
...
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
@Override
public void publishEvent(Object event) {
publishEvent(event, null);
}
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);
}
// 在这里确定要发布的事件对象
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<Object>(this, event);
if (eventType == null) {
eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
}
}
// 在这里委托ApplicationEventMulticaster进行事件发布
if (this.earlyApplicationEvents != null) {
//在注册完毕监听器时会将这里的事件发布出去然后置为null(防止publish的事件在注册监听器之前广播)
this.earlyApplicationEvents.add(applicationEvent);
}
else {
//获取容器的广播者进行事件广播
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
}
2、ApplicationEvent实现
//从这里可以看出事件的实现并没有定义太多功能,更多的只是作为一种标示,利用类来表示是什么事件而已
//当然也可以定义一些字段来传递信息
public class ContextStartedEvent extends ApplicationContextEvent {
public ContextStartedEvent(ApplicationContext source) {
super(source);
}
}
3、ApplicationEventMulticaster的实现AbstractApplicationEventMulticaster、SimpleApplicationEventMulticaster
AbstractApplicationEventMulticaster提供一个基本的事件广播的监听器的增删功能,而广播事件
multicastEvent(ApplicationEvent event)
multicastEvent(ApplicationEvent event, ResolvableType eventType)
的方法交给交给了子类SimpleApplicationEventMulticaster来实现
ResolvableType 这个类其实就是封装的java.lang.reflect.Type
//实现事件广播
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
...
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
//如果定义了事件类型则只判断支持该类型的监听器进行广播事件(判断是否支持通过子接口里的supportsEventType(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() {
//在这里就是调用listener.onApplicationEvent(event)方法通知监听器
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
...
}
4、ApplicationListener的实现
其实到这里 就是可以任意扩展的地方啦,只要你的对象是交给Spring容器管理的,在容器
初始化时就会注册监听器,然后在容器发布事件的时候就能接收到相应的事件了
这里看一下SqlSessionFactoryBean的实现:
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
...
@Override
public void onApplicationEvent(ApplicationEvent event) {
//这里由于容器产生任何事件都会调用该方法,所以使用instanceof 来区分是什么事件。
if (failFast && event instanceof ContextRefreshedEvent) {
// fail-fast -> check all statements are completed
this.sqlSessionFactory.getConfiguration().getMappedStatementNames();
}
}
...
}
总结:
其实监听器就是观察者模式的实现,可以参考jdk提供的java.util.Observable,java.util.Observer
就更能理解spring在这里的设计,spring将各个环节都进行了接口抽象,而且在实现时也会使用abstract类进行具有通用性的方法进行分层实现,使得很多方法就更具有复用性,当然这样扩展性也提现出来了,如果有特殊需求,可以继承一下就得到了很多基本功能,很好的提现了从抽象到具体的面向对象的设计思想。而像getTaskExecutor()这种获取一些对象通过一个protected的get方法来获取,使得程序的灵活性大大的提高了,充分的利用多态的特性。