容器事件和事件监听器
代码地址:WangChao-ly/chao-spring at event-and-event-listener (github.com)
建议订阅博主专栏,从下到上系统手写spring源码,体会其中过程!
概括:事件的监听和发布,内容符合其字面意思,就是先注册好事件监听者。然后在事件触发时,通知所有的监听者,有事件来了,看是不是该监听者感兴趣的事件,如果是的话,会执行相对应的操作。
事件监听
- 当应用程序发布一个事件时,实现了ApplicationListener接口的类会被通知,并且可以对该事件做出响应。onApplicationEvent方法的作用是处理应用程序事件。当一个事件被发布时,Spring框架会遍历所有实现了ApplicationListener接口的类,并调用它们的onApplicationEven。
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* 处理应用程序事件
* @param event
*/
void onApplicationEvent(E event);
}
- ApplicationEventMulticaster:该接口提供添加监听器、移除监听器和广播的作用
- AbstractApplicationEventMulticaster:该类实现了上面的接口,用一个Set集合存储了注册的监听器
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {
public final Set<ApplicationListener<ApplicationEvent>> applicationListeners = new HashSet<>();
private BeanFactory beanFactory;
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
applicationListeners.add((ApplicationListener<ApplicationEvent>)listener);
}
@Override
public void removeApplicationListener(ApplicationListener<?> listener) {
applicationListeners.remove((ApplicationListener<ApplicationEvent>)listener);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
事件发布和注册事件监听器
- 事件发布接口:ApplicationContext继承了该接口,在AbstractApplicationContext中实现了该接口,调用广播方法。
public interface ApplicationEventPublisher {
/**
* 发布事件
*
* @param event
*/
void publishEvent(ApplicationEvent event);
}
/**
* 注册事件监听器
*/
protected void registerListeners(){
//bean和名称和该类型的bean,Map集合
Collection<ApplicationListener> applicationListeners = getBeanOfType(ApplicationListener.class).values();
for(ApplicationListener applicationListener:applicationListeners){
applicationEventMulticaster.addApplicationListener(applicationListener);
}
}
/**
* 发布容器刷新完成事件
*/
protected void finishRefresh() {
publishEvent(new ContextRefreshedEvent(this));
}
@Override
public void publishEvent(ApplicationEvent applicationEvent){
applicationEventMulticaster.multicastEvent(applicationEvent);
}
protected void initApplicationEventMulticaster(){
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//实例化事件发布者
applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//将事件发布者注册到容器中
beanFactory.addSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME,applicationEventMulticaster);
}
- 然后广播方法中通知注册的监听器,看监听器是否对事件感兴趣,拿到监听器中泛型类,看是否匹配(同一类或者是其子类),如果匹配表示感兴趣,执行相应的处理方法。
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster{
public SimpleApplicationEventMulticaster(BeanFactory beanFactory){
setBeanFactory(beanFactory);
}
@Override
public void multicastEvent(ApplicationEvent event) {
for(ApplicationListener<ApplicationEvent> applicationListener :applicationListeners){
if(supportsEvent(applicationListener,event)){
//调用处理事件的方法
applicationListener.onApplicationEvent(event);
}
}
}
/**
* 监听器是否对事件感兴趣
* @param applicationListener
* @param event
* @return
*/
protected boolean supportsEvent(ApplicationListener<ApplicationEvent> applicationListener,ApplicationEvent event){
//获取对象所实现的第一个泛型接口类型
Type type = applicationListener.getClass().getGenericInterfaces()[0];
//获取到泛型接口的第一个实际类型参数
Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0];
String className = actualTypeArgument.getTypeName();
Class<?> eventClass;
try {
eventClass = Class.forName(className);
}catch (ClassNotFoundException e){
throw new BeansException("wrong event class name: " + className);
}
//用于确定一个类是否可以从另一个类进行赋值,该事件的子类事件也能匹配上
return eventClass.isAssignableFrom(event.getClass());
}
}
- 测试用例看具体代码