(造轮子)手写Spring框架-容器事件和事件监听器

210 阅读2分钟

容器事件和事件监听器

代码地址:WangChao-ly/chao-spring at event-and-event-listener (github.com)

建议订阅博主专栏,从下到上系统手写spring源码,体会其中过程!

概括:事件的监听和发布,内容符合其字面意思,就是先注册好事件监听者。然后在事件触发时,通知所有的监听者,有事件来了,看是不是该监听者感兴趣的事件,如果是的话,会执行相对应的操作。

事件监听

  1. 当应用程序发布一个事件时,实现了ApplicationListener接口的类会被通知,并且可以对该事件做出响应。onApplicationEvent方法的作用是处理应用程序事件。当一个事件被发布时,Spring框架会遍历所有实现了ApplicationListener接口的类,并调用它们的onApplicationEven。
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    /**
     * 处理应用程序事件
     * @param event
     */
    void onApplicationEvent(E event);
}
  1. ApplicationEventMulticaster:该接口提供添加监听器、移除监听器和广播的作用
  2. 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;
    }
}

事件发布和注册事件监听器

  1. 事件发布接口: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);
    }
  1. 然后广播方法中通知注册的监听器,看监听器是否对事件感兴趣,拿到监听器中泛型类,看是否匹配(同一类或者是其子类),如果匹配表示感兴趣,执行相应的处理方法。
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());
    }
}
  1. 测试用例看具体代码