Spring 观察者模式使用

1.概述

在设计模式中,观察者模式是一个比较常用的设计模式。维基百科解释如下:

观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。

此种模式通常被用来实时事件处理系统。

在我们日常业务开发中,观察者模式对我们很大的一个作用,在于实现业务的解耦。以用户注册的场景来举例子,假设在用户注册完成时,需要给该用户发送邮件、发送优惠劵等等操作,如下图所示:

java观察者模式详解 spring 观察者模式_java

  • UserService 在完成自身的用户注册逻辑之后,仅仅只需要发布一个 UserRegisterEvent 事件,而无需关注其它拓展逻辑。
  • 其它 Service 可以自己订阅 UserRegisterEvent 事件,实现自定义的拓展逻辑。

友情提示:很多时候,我们会把观察者模式发布订阅模式放在一起对比。

简单来说,发布订阅模式属于广义上的观察者模式,在观察者模式的 Subject 和 Observer 的基础上,引入 Event Channel 这个中介,进一步解耦。如下图所示:

java观察者模式详解 spring 观察者模式_观察者模式_02

2.Spring 事件机制

Spring 基于观察者模式,实现了自身的事件机制,由三部分组成:

  • 事件 ApplicationEvent:通过继承它,实现自定义事件。另外,通过它的 source 属性可以获取事件源, timestamp 属性可以获取发生事件。
  • 事件发布者 ApplicationEventPublisher:通过实现它,可以进行事件的发布,也可以实现ApplicationContentAware。
  • 事件监听器 ApplicationListener:通过实现它,进行指定类型的事件的监听。

友情提示:JDK 也内置了事件机制的实现,考虑到通用性,Spring 的事件机制是基于它之上进行拓展。因此,ApplicationEvent 继承自 java.util.EventObject,ApplicationListener 继承自 java.util.EventListener

3.入门示例

SpringEvent 的使用

  1. 创建消息对象的实体类 (该类需要继承ApplicationEvent)
    public class DemoEvent extends ApplicationEvent {
private static final long serialVersionUID = 5613108322901123046L;
@Getter
@Setter
private Long id;

@Getter
@Setter
private String message;

public DemoEvent(Object source, Long id, String message) {
    super(source);
    this.id = id;
    this.message = message;
}

}

  1. 创建生产者
    生产者类需要实现ApplicationContextAware接口来注入ApplicationContext对象
@Slf4j
@Component
public class DemoEventPublisher implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    public void publish(Long id, String message) {
        log.info("做一些业务处理");
        publisher.publishEvent(new DemoEvent(this, id,  message));
    }
}
  1. 创建消费者
    使用@EventListener注解
    如果需要异步的话,加上@Async注解
    示例
@Slf4j
@Component
public class DemoEventListener {

    @EventListener
    public void onApplicationEvent(DemoEvent demoEvent) {
        log.info(">>>>>>>>>DemoListener2>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        log.info("收到了:" + demoEvent.getSource() + "消息;时间:" + demoEvent.getTimestamp());
        log.info("消息:" + demoEvent.getId() + ":" + demoEvent.getMessage());
    }
}
  1. 测试
@Autowired
    private DemoEventPublisher demoEventPublisher;

    @Test
    public void testEventLister() {
        log.info("开始生产消息:==========");
        demoEventPublisher.publish(1L, "hello");
    }

java观察者模式详解 spring 观察者模式_java_03