未央花博客

观察者设计模式-spring中的实现

观察者设计模式

用订阅和发布来理解观察者设计模式更好。
为什么呢?因为监听器这个名词听起来是一个主动的,可实际监听器是一个被动的玩意
比如我们事件源发布一个事件,然后监听器订阅了这个事件就能做出动作。
里面涉及到三个对象:事件源,事件、监听器,可以好好理解一下

当事件发生,就会通知监听器。
事件源:当前发生的事件属于哪个事件源

1、观察者设计模式

特点:

观察者 implements Observer重写update方法

优点

松耦合

通知不错过

    由于被动接受,正常情况下不会错过主题的改变通知。而主动获取的话,由于时机选取问题,可能导致错过某些状态。

Java中JDK的实现

Java中有观察者模式使用的API

开关的重要性

public void move() {
    // 这是开关
    setChanged();
    // 调用相应的观察者
    notifyObservers();
}

2、Spring中的实现方式

2.1 Spring中的Events

事件通过org.springframework.context.ApplicationEvent实例来表示。这个抽象类继承扩展了java.util.EventObject,可以使用EventObject中的getSource方法,我们可以很容易地获得所发生的给定事件的对象。这里,事件存在两种类型

  1. 与应用程序上下文相关联

    所有这种类型的事件都继承自org.springframework.context.event.ApplicationContextEvent类。它们应用于由org.springframework.context.ApplicationContext引发的事件(其构造函数传入的是ApplicationContext类型的参数)。这样,我们就可以直接通过应用程序上下文的生命周期来得到所发生的事件:ContextStartedEvent在上下文启动时被启动,当它停止时启动ContextStoppedEvent,当上下文被刷新时产生ContextRefreshedEvent,最后在上下文关闭时产生ContextClosedEvent

  2. 与request 请求相关联

    org.springframework.web.context.support.RequestHandledEvent实例来表示,当在ApplicationContext中处理请求时,它们被引发。

2.2 Spring如何将事件分配给专门的监听器?

这个过程由事件广播器来实现,由org.springframework.context.event.ApplicationEventMulticaster接口的实现表示。此接口定义了3种方法:

  1. addApplicationListener() 添加新的监听器:定义了两种方法来添加新的监听器:addApplicationListener(ApplicationListener<?> listener)addApplicationListenerBean(String listenerBeanName)。当监听器对象已知时,可以应用第一个。如果使用第二个,我们需要将bean name 得到listener对象(依赖查找DL),然后再将其添加到listener列表中
  2. removeApplicationListenerBean(String listenerBeanName) 删除监听器:添加方法一样,我们可以通过传递对象来删除一个监听器(removeApplicationListener(ApplicationListener<?> listener)或通过传递bean名称。第三种方法,removeAllListeners()用来删除所有已注册的监听器
  3. multicastEvent(ApplicationEvent event)将事件发送给已注册的监听器。

2.2.1 继承ApplicationEventMulticaster接口的类

AbstractApplicationEventMulticaster类、SimpleApplicationEventMulticaster类,这两个类很重要,springboot中就是利用的这两个类。

源码解析:这个源码部分解析可以参考这篇博客:springboot 源码解析(一)ApplicationListener

3、自己写一个监听器

spring当中写,由于没有去改动源码,所以写的监听器稍微改动了点。

  1. Test.java

    public class Test {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context =
                    new AnnotationConfigApplicationContext(App.class);
    
            MailBean bean = context.getBean(MailBean.class);
            // 发布一个SpringMailEvent事件
            bean.sendMail();
        }
    }
  2. MailBean.java

    @Component
    public class MailBean {
    
        @Autowired
        ApplicationContext applicationContext;
    
        public void sendMail() {
            // ApplicationContext也是事件源。
            // 发布一个事件
            applicationContext.publishEvent(new SpringMailEvent(applicationContext));
        }
    }
  3. SpringMailEvent.java

    public class SpringMailEvent extends ApplicationEvent{
        // 可以是事件发生的内容
        private String content;
    
        public SpringMailEvent(Object source) {
            super(source);
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    }
  4. SpringMailListener.java

    @Component
    public class SpringMailListener implements ApplicationListener<SpringMailEvent> {
        @Override
        public void onApplicationEvent(SpringMailEvent event) {
            System.out.println("mail send========");
        }
    }

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »