Spring:事件发布机制

古城微笑少年丶 2022-10-31 05:23 303阅读 0赞

起因是在看Spring Security时,看到如下代码

  1. protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
  2. Authentication authResult) throws IOException, ServletException {
  3. ...
  4. if (this.eventPublisher != null) {
  5. this.eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
  6. }
  7. ...
  8. }

这让我想起的第一个念头就是观察者模式,我尝试写了下案例,如下

  1. public class Subject {
  2. int state ;
  3. List<Observer> observerList = new ArrayList<Observer>();
  4. public void change(){
  5. state = 0;
  6. if(state==0){
  7. observerList.forEach((k)->{ k.update();});
  8. }
  9. }
  10. public void register(Observer observer){
  11. observerList.add(observer);
  12. }
  13. public static void main(String[] args) {
  14. Subject subject = new Subject();
  15. Observer1 observer1 = new Observer1();
  16. Observer2 observer2 = new Observer2();
  17. subject.register(observer1);
  18. subject.register(observer2);
  19. subject.change();
  20. }
  21. }
  22. public interface Observer {
  23. void update();
  24. }
  25. public class Observer1 implements Observer {
  26. @Override
  27. public void update() {
  28. System.out.println("Observer1发生改变");
  29. }
  30. }
  31. public class Observer2 implements Observer {
  32. @Override
  33. public void update() {
  34. System.out.println("Observer2发生改变");
  35. }
  36. }

观察者模式就是典型的就是发布-订阅模式,通过维护一个观察者队列,长期、持续地监听某个参数、数值的变化,来决定是否会通过观察者们,很简单的一个模式。

在Spring中,它又是怎样的呢,来看下面

好家伙链接

Spring对事件驱动模型提供了支持,一样分为3块:

1、事件

从继承结构来看,一共有4个实现类,从类名来看就能很容易明白其作用,平时我们使用的时候只要实现ApplicationEvent抽象类即可。

在这里插入图片描述

2、发布者

从下面的继承结构来看,我们可以通过继承ApplicationEventPublisher接口,重写publishEvent()方法来实现自定义或者实现ApplicationContextAware接口也也是看主意,通过注入ApplicationContext,再重写publishEvent()方法。

在这里插入图片描述

我发现在AbstractApplicationContext类中添加了对监听者的注册、获取等方法。保存监听者们是一个set集合,他们最后都会给注册到 ApplicationEventMulticaster 的set中。

  1. // 暂时保存在set中
  2. public void addApplicationListener(ApplicationListener<?> listener) {
  3. if (this.applicationEventMulticaster != null) {
  4. this.applicationEventMulticaster.addApplicationListener(listener);
  5. }
  6. this.applicationListeners.add(listener);
  7. }

注册到ApplicationEventMulticaster

  1. protected void registerListeners() {
  2. // 遍历集合,注册监听者
  3. for (ApplicationListener<?> listener : getApplicationListeners()) {
  4. getApplicationEventMulticaster().addApplicationListener(listener);
  5. }
  6. // Do not initialize FactoryBeans here: We need to leave all regular beans
  7. // uninitialized to let post-processors apply to them!
  8. String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
  9. for (String listenerBeanName : listenerBeanNames) {
  10. getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
  11. }
  12. // Publish early application events now that we finally have a multicaster...
  13. Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
  14. this.earlyApplicationEvents = null;
  15. if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
  16. for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
  17. getApplicationEventMulticaster().multicastEvent(earlyEvent);
  18. }
  19. }
  20. }

发布事假,发现它需要获取一个ApplicationEventMulticaster

  1. protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
  2. ...
  3. if (this.earlyApplicationEvents != null) {
  4. this.earlyApplicationEvents.add(applicationEvent);
  5. }
  6. else {
  7. getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
  8. }
  9. ...
  10. }

ApplicationEventMulticaster 的初始化,查看配置中有没有进行配置,没有则创建SimpleApplicationEventMulticaster实例并进行赋值。

  1. protected void initApplicationEventMulticaster() {
  2. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  3. if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
  4. this.applicationEventMulticaster =
  5. beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
  6. }
  7. else {
  8. this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
  9. beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
  10. }
  11. }

我们将发布的方法点到,最后,发现它仅仅只是调用Listener的onApplicationEvent

  1. private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
  2. try {
  3. listener.onApplicationEvent(event);
  4. }
  5. catch (ClassCastException ex) {
  6. ...
  7. }
  8. }

3、监听者

我们通过实现ApplicationListener接口,重写ApplicationListener()方法就可以进行使用

在这里插入图片描述

从上面看来,Spring对事件驱动模型就是装饰器模式,不过放监听者的地方是ApplicationEventMulticaster。

发表评论

表情:
评论列表 (有 0 条评论,303人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring 事件发布

    前言 事件发布是 Spring 框架中最容易被忽视的功能之一,但实际上它是一个很有用的功能。使用事件机制可以将同一个应用系统内互相耦合的代码进行解耦,并且可以将事件与 S

    相关 Spring事件机制

    1.背景 事件驱动的一个常见形式便是发布-订阅模式。在跨进程的通信间,我们通常采用引入 MQ (消息队列) 来实现消息的发布和订阅。目前主流应用的架构中,均采用消息的发布

    相关 spring事件机制

    事件驱动模型简介 事件驱动模型也就是我们常说的观察者,或者发布-订阅模型;理解它的几个关键点: 1. 首先是一种对象间的一对多的关系;最简单的如交通信号灯,信号灯是目

    相关 spring事件机制

    事件驱动模型简介 事件驱动模型也就是我们常说的观察者,或者发布-订阅模型;理解它的几个关键点: 首先是一种对象间的一对多的关系;最简单的如交通信号灯,信号灯是目标