Spring 自带的观察者模式

Spring 观察者模式使用

1.概述

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

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

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

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

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

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

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

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;
    }
    

    }

  2. 创建生产者

    生产者类需要实现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));
        }
    }
    
  3. 创建消费者

    使用@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());
        }
    }
    
  4. 测试

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

    image-20220324160133095

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值