您的位置:首页 > 编程语言 > Java开发

spring源码学习之容器监听器篇

2017-04-12 13:32 363 查看

一、监听器相关接口

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

4000
//实现事件广播
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方法来获取,使得程序的灵活性大大的提高了,充分的利用多态的特性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring 源码