天天看点

关于Spring的事件监听机制,你知道多少?

作者:小心程序猿QAQ

前言

前一节,我们了解了Spring 提供的 Aware接口,我们可以通过这个实现这个接口的一些类获取到我们需要的东西。具体内容见前一节。 Spring 也提供了一种单机的事件机制。可以通过发送、监听,来实现一些异步操作。 使用这种 类似 MQ 的事件机制,我们可以通过 这个事件机制来完成一些自己的业务操作。在我们使用spring提供的事件机制时,我们只需要关注自己的事件,和自己的事件处理器。所有的事件都会继承 ApplicationEvent,然后再完成对于自己时间的监听器,监听器都 实现 ApplicationListener接口,实现 onApplicationEvent方法,来处理监听到的事件。 下面是事件注册、监听的整体过程。主要就是 在spring容器加载的时候,把所有的监听器统一注册到SimpleApplicationEventMulticaster事件分发器中,然后统一处理。

关于Spring的事件监听机制,你知道多少?
关于Spring的事件监听机制,你知道多少?

实现

ApplicationEvent 事件基类, EventObject是java提供的一个类

public class ApplicationEvent extends EventObject {
    /**
     * Constructs a prototypical Event.
     *
     * @param source The object on which the Event initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public ApplicationEvent(Object source) {
        super(source);
    }
}
复制代码           

ApplicationContextEvent系统事件

public class ApplicationContextEvent extends ApplicationEvent {
    /**
     * Constructs a prototypical Event.
     *
     * @param source The object on which the Event initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public ApplicationContextEvent(ApplicationContext source) {
        super(source);
    }


    public final ApplicationContext getApplicationContext() {
        return (ApplicationContext) getSource();
    }
}
复制代码           

ApplicationEventPublisher 事件发布器,统一发布事件。

public interface ApplicationEventPublisher {

    /**
     * 发布事件
     * @param event 事件
     */
    void publishEvent(ApplicationEvent event);

}
复制代码           

ApplicationEventMulticaster事件管理、分发器。ApplicationEventMulticaster统一定义公共行为, AbstractApplicationEventMulticaster抽象类处理公共逻辑。SimpleApplicationEventMulticaster默认分发器,只需要执行具体的分发逻辑。supportEvent方法检查事件是否需要被处理。

public interface ApplicationEventMulticaster {

    /**
     * Add a listener to be notified of all events.
     * @param listener the listener to add
     */
    void addApplicationListener(ApplicationListener listener);

    /**
     * Remove a listener from the notification list.
     * @param listener the listener to remove
     */
    void removeApplicationListener(ApplicationListener listener);

    /**
     * Multicast the given application event to appropriate listeners.
     * @param event the event to multicast
     */
    void multicastEvent(ApplicationEvent event);

}

public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {

    private final Set<ApplicationListener> applicationListeners = new LinkedHashSet<>();

    private BeanFactory beanFactory;

    @Override
    public void addApplicationListener(ApplicationListener listener) {
        this.applicationListeners.add((ApplicationListener) listener);
    }

    @Override
    public void removeApplicationListener(ApplicationListener listener) {
        this.applicationListeners.remove(listener);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event) throws BeansException {
        LinkedList<ApplicationListener<?>> allListeners = new LinkedList<>();
        for (ApplicationListener<?> listener : applicationListeners) {
            if (supportEvent(listener, event)) {
                allListeners.add(listener);
            }
        }
        return allListeners;
    }

    /**
     * 监听器是否对该事件感兴趣
     */
    protected boolean supportEvent(ApplicationListener listener, ApplicationEvent event) throws BeansException {
        // 检查事件是否需要关注
        Class<? extends ApplicationListener> clazz = listener.getClass();
        Class<?> targetClass = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;
        Type genericInterface = targetClass.getGenericInterfaces()[0];
        Type typeArgument = ((ParameterizedType) genericInterface).getActualTypeArguments()[0];
        String className = typeArgument.getTypeName();
        Class<?> eventClassName;
        try {
            eventClassName = Class.forName(className);
        } catch (ClassNotFoundException e) {
            throw new BeansException("wrong event class name: " + className);
        }
        // 判定此 eventClassName 对象所表示的类或接口与指定的 event.getClass() 参数所表示的类或接口是否相同,或是否是其超类或超接口。
        // isAssignableFrom是用来判断子类和父类的关系的,或者接口的实现类和接口的关系的,默认所有的类的终极父类都是Object。如果A.isAssignableFrom(B)结果是true,证明B可以转换成为A,也就是A可以由B转换而来。
        return eventClassName.isAssignableFrom(event.getClass());
    }
}

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster{
    @Override
    public void multicastEvent(ApplicationEvent event) {
        try {
            // 实现事件处理
            Collection<ApplicationListener<?>> listeners = getApplicationListeners(event);
            for (ApplicationListener listener : listeners) {
                listener.onApplicationEvent(event);
            }
        }catch (Exception e){
            // 执行失败
        }
    }
}
复制代码           

AbstractApplicationContext容器刷新,完成 事件分发器的注册、事件监听器的注册。

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";

    private ApplicationEventMulticaster applicationEventMulticaster;

	/**
     * 模板方法,控制定义spring上下文的刷新与创建
     * @throws BeansException
     */
    @Override
    public void refresh() throws BeansException {
        // 1. 创建beanFactory,加载beanDefinition
        refreshBeanFactory();
        // 2. 获取 beanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 3. 添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        // 4. bean 实例化之前 执行 beanFactoryPostProcessor
        invokeBeanFactoryPostProcessors(beanFactory);
        // 5. beanPostProcessor 完成 bean 实例化后的注册操作
        registerBeanPostProcessors(beanFactory);
        // 6. 提前实例化 单例bean 对象
        beanFactory.preInstantiateSingletons();
        // 初始化事件发布者
        initApplicationEventMulticaster();
        // 注册监听事件
        registerListeners();
        // 完成刷新
        finishRefresh();
    }

    private void finishRefresh() {
        publishEvent(new ContextRefreshedEvent(this));
    }

    private void registerListeners() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        Collection<ApplicationListener> listeners = beanFactory.getBeansOfType(ApplicationListener.class).values();
        for (ApplicationListener listener : listeners) {
            applicationEventMulticaster.addApplicationListener(listener);
        }
    }

    private void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        applicationEventMulticaster = new SimpleApplicationEventMulticaster();
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster);
    }


    @Override
    public void publishEvent(ApplicationEvent event) {
        applicationEventMulticaster.multicastEvent(event);
    }

}
复制代码           

测试

定义事件、定义事件监听器。

/**
 * @author huangle
 * @date 2023/3/14 16:21
 */
public class ConsumerEvent extends ApplicationContextEvent {

    private String msgId;

    private String msgBody;

    public ConsumerEvent(ApplicationContext source, String msgId, String msgBody) {
        super(source);
        this.msgId = msgId;
        this.msgBody = msgBody;
    }
}


public class ConsumerEventLister implements ApplicationListener<ConsumerEvent> {
    @Override
    public void onApplicationEvent(ConsumerEvent consumerEvent) {
        System.out.println(this.getClass()+"接受到消息:"+consumerEvent.getMsgId()+"-"+consumerEvent.getMsgBody());
    }
}

复制代码           

注入事件监听器

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean id="consumerEventLister" class="cn.anoxia.springframework.beans.factory.support.event.ConsumerEventLister"/>
    <bean id="applicationRefershEventListener" class="cn.anoxia.springframework.beans.factory.support.event.ApplicationRefershEventListener"/>
    <bean id="applicationCloseEventListener" class="cn.anoxia.springframework.beans.factory.support.event.ApplicationCloseEventListener"/>
</beans>
复制代码           

发布事件

@Test
    public void testEvent() throws BeansException{
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
        applicationContext.publishEvent(new ConsumerEvent(applicationContext, UUID.randomUUID().toString(),"消息发送成功!"));
        applicationContext.registerShutdownHook();
    }
复制代码           
关于Spring的事件监听机制,你知道多少?

作者:Anoxia1

链接:https://juejin.cn/post/7225891176532770877