当前位置:   article > 正文

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

spring事件监听机制

前言

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

实现

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

  1. public class ApplicationEvent extends EventObject {
  2. /**
  3. * Constructs a prototypical Event.
  4. *
  5. * @param source The object on which the Event initially occurred.
  6. * @throws IllegalArgumentException if source is null.
  7. */
  8. public ApplicationEvent(Object source) {
  9. super(source);
  10. }
  11. }
  12. 复制代码

ApplicationContextEvent系统事件

  1. public class ApplicationContextEvent extends ApplicationEvent {
  2. /**
  3. * Constructs a prototypical Event.
  4. *
  5. * @param source The object on which the Event initially occurred.
  6. * @throws IllegalArgumentException if source is null.
  7. */
  8. public ApplicationContextEvent(ApplicationContext source) {
  9. super(source);
  10. }
  11. public final ApplicationContext getApplicationContext() {
  12. return (ApplicationContext) getSource();
  13. }
  14. }
  15. 复制代码

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

  1. public interface ApplicationEventPublisher {
  2. /**
  3. * 发布事件
  4. * @param event 事件
  5. */
  6. void publishEvent(ApplicationEvent event);
  7. }
  8. 复制代码

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

  1. public interface ApplicationEventMulticaster {
  2. /**
  3. * Add a listener to be notified of all events.
  4. * @param listener the listener to add
  5. */
  6. void addApplicationListener(ApplicationListener listener);
  7. /**
  8. * Remove a listener from the notification list.
  9. * @param listener the listener to remove
  10. */
  11. void removeApplicationListener(ApplicationListener listener);
  12. /**
  13. * Multicast the given application event to appropriate listeners.
  14. * @param event the event to multicast
  15. */
  16. void multicastEvent(ApplicationEvent event);
  17. }
  18. public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {
  19. private final Set<ApplicationListener> applicationListeners = new LinkedHashSet<>();
  20. private BeanFactory beanFactory;
  21. @Override
  22. public void addApplicationListener(ApplicationListener listener) {
  23. this.applicationListeners.add((ApplicationListener) listener);
  24. }
  25. @Override
  26. public void removeApplicationListener(ApplicationListener listener) {
  27. this.applicationListeners.remove(listener);
  28. }
  29. @Override
  30. public void setBeanFactory(BeanFactory beanFactory) {
  31. this.beanFactory = beanFactory;
  32. }
  33. protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event) throws BeansException {
  34. LinkedList<ApplicationListener<?>> allListeners = new LinkedList<>();
  35. for (ApplicationListener<?> listener : applicationListeners) {
  36. if (supportEvent(listener, event)) {
  37. allListeners.add(listener);
  38. }
  39. }
  40. return allListeners;
  41. }
  42. /**
  43. * 监听器是否对该事件感兴趣
  44. */
  45. protected boolean supportEvent(ApplicationListener listener, ApplicationEvent event) throws BeansException {
  46. // 检查事件是否需要关注
  47. Class<? extends ApplicationListener> clazz = listener.getClass();
  48. Class<?> targetClass = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;
  49. Type genericInterface = targetClass.getGenericInterfaces()[0];
  50. Type typeArgument = ((ParameterizedType) genericInterface).getActualTypeArguments()[0];
  51. String className = typeArgument.getTypeName();
  52. Class<?> eventClassName;
  53. try {
  54. eventClassName = Class.forName(className);
  55. } catch (ClassNotFoundException e) {
  56. throw new BeansException("wrong event class name: " + className);
  57. }
  58. // 判定此 eventClassName 对象所表示的类或接口与指定的 event.getClass() 参数所表示的类或接口是否相同,或是否是其超类或超接口。
  59. // isAssignableFrom是用来判断子类和父类的关系的,或者接口的实现类和接口的关系的,默认所有的类的终极父类都是Object。如果A.isAssignableFrom(B)结果是true,证明B可以转换成为A,也就是A可以由B转换而来。
  60. return eventClassName.isAssignableFrom(event.getClass());
  61. }
  62. }
  63. public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster{
  64. @Override
  65. public void multicastEvent(ApplicationEvent event) {
  66. try {
  67. // 实现事件处理
  68. Collection<ApplicationListener<?>> listeners = getApplicationListeners(event);
  69. for (ApplicationListener listener : listeners) {
  70. listener.onApplicationEvent(event);
  71. }
  72. }catch (Exception e){
  73. // 执行失败
  74. }
  75. }
  76. }
  77. 复制代码

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

  1. public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
  2. public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
  3. private ApplicationEventMulticaster applicationEventMulticaster;
  4. /**
  5. * 模板方法,控制定义spring上下文的刷新与创建
  6. * @throws BeansException
  7. */
  8. @Override
  9. public void refresh() throws BeansException {
  10. // 1. 创建beanFactory,加载beanDefinition
  11. refreshBeanFactory();
  12. // 2. 获取 beanFactory
  13. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  14. // 3. 添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext
  15. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  16. // 4. bean 实例化之前 执行 beanFactoryPostProcessor
  17. invokeBeanFactoryPostProcessors(beanFactory);
  18. // 5. beanPostProcessor 完成 bean 实例化后的注册操作
  19. registerBeanPostProcessors(beanFactory);
  20. // 6. 提前实例化 单例bean 对象
  21. beanFactory.preInstantiateSingletons();
  22. // 初始化事件发布者
  23. initApplicationEventMulticaster();
  24. // 注册监听事件
  25. registerListeners();
  26. // 完成刷新
  27. finishRefresh();
  28. }
  29. private void finishRefresh() {
  30. publishEvent(new ContextRefreshedEvent(this));
  31. }
  32. private void registerListeners() {
  33. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  34. Collection<ApplicationListener> listeners = beanFactory.getBeansOfType(ApplicationListener.class).values();
  35. for (ApplicationListener listener : listeners) {
  36. applicationEventMulticaster.addApplicationListener(listener);
  37. }
  38. }
  39. private void initApplicationEventMulticaster() {
  40. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  41. applicationEventMulticaster = new SimpleApplicationEventMulticaster();
  42. beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster);
  43. }
  44. @Override
  45. public void publishEvent(ApplicationEvent event) {
  46. applicationEventMulticaster.multicastEvent(event);
  47. }
  48. }
  49. 复制代码

测试

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

  1. /**
  2. * @author huangle
  3. * @date 2023/3/14 16:21
  4. */
  5. public class ConsumerEvent extends ApplicationContextEvent {
  6. private String msgId;
  7. private String msgBody;
  8. public ConsumerEvent(ApplicationContext source, String msgId, String msgBody) {
  9. super(source);
  10. this.msgId = msgId;
  11. this.msgBody = msgBody;
  12. }
  13. }
  14. public class ConsumerEventLister implements ApplicationListener<ConsumerEvent> {
  15. @Override
  16. public void onApplicationEvent(ConsumerEvent consumerEvent) {
  17. System.out.println(this.getClass()+"接受到消息:"+consumerEvent.getMsgId()+"-"+consumerEvent.getMsgBody());
  18. }
  19. }
  20. 复制代码

注入事件监听器

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

发布事件

  1. @Test
  2. public void testEvent() throws BeansException{
  3. ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
  4. applicationContext.publishEvent(new ConsumerEvent(applicationContext, UUID.randomUUID().toString(),"消息发送成功!"));
  5. applicationContext.registerShutdownHook();
  6. }
  7. 复制代码

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/799304
推荐阅读
相关标签
  

闽ICP备14008679号