观察者模式-Spring事件发布订阅实现和源码分析

本文深入解析Spring框架中的事件发送和接收机制,包括通过ApplicationContext和ApplicationEventPublisher发送事件,以及使用ApplicationListener接口和@EventListener注解接收事件的具体实现。探讨了事件驱动模型在Spring中的应用,及其与观察者模式的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设计模式-总览icon-default.png?t=LBL2https://mp.csdn.net/mp_blog/creation/editor/122202507目录

1、Spring事件的发送方式

2、Spring事件的接收方式

1)、继承 ApplicationListener 接口,实现 onApplicationEvent方法

总结

2)、使用注解@EventListener


    在上一篇观察者模式-jdk实现和自定义实现分析后,发现jdk已经简化了很多的开发成本。然而,我们现在很多时候开发环境已经在Spring的ApplicationContext容器中,已经必须要自己再去使用jdk实现(当然上一篇博客了解观察者模式的实现我觉得还是很重要的)。Spring认为发布订阅主题,其实可以理解为事件驱动的编码,先来实现以下Spring容器中的事件发布订阅。

    个人认为事件驱动的发布订阅模型,也算是观察者模式(不论是推还是拉的方式)。spring事件驱动(特别是SpringBoot扩展后)可以很方便的进行实现,那么肯定不会自己去使用Observer的模式。

1、Spring事件的发送方式

可以使用下面两种方式,但其实都是一样的,后面进行分析:

applicationContext.publishEvent(new UserEvent(user));
applicationEventPublisher.publishEvent(new UserEvent(user));

@Service("eventUserService")
public class UserService implements ApplicationContextAware, 
    ApplicationEventPublisherAware {

    private ApplicationContext applicationContext;
    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

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

    public String addUser(User user) {
        // 保存用户
        user.setId(1L);
        user.setName("name-1");
        // 发生事件(发邮件、发短信、、、)
        applicationContext.publishEvent(new UserEvent(user));
        // 两种发送方式一致
        applicationEventPublisher.publishEvent(new UserEvent(user));
        return "ok";
    }

}

2、Spring事件的接收方式

1)、继承 ApplicationListener 接口,实现 onApplicationEvent方法

    详细见我写的Spring源码分析:Spring源码-事件监听机制(实现EventListener接口)

总结

1、ApplicationContext发送事件是委托给了一个  Spring容器在refresh时初始化的SimpleApplicationEventMulticaster

bean(由于没有初始化内部线程池对象,所以事件是同步发送的)。

2、发送前先获取事件的ResolvableType类型(当前为OrderEvent clazz)和事件源类型(当前为String)

3、获取监听者列表。 先去自己Bean内部先查询缓存,否则从BeanFactory中获取所有单利bean进行匹配(再放入缓存ConturrentHashMap)。

4、监听者列表循环(同步或异步)地调用我们自己写的监听方法OnApplicationEvent。

2)、使用注解@EventListener

    详细见写的另一篇博客:Spring源码-事件监听机制(@EvnetListener方式)

总结(与上面相同和不同之处):

相同:

1、ApplicationContext的refresh方法还是初始化了SimpleApplicationEventMulticaster

2、发送事件式还是先获取ResolvableType类型,再获取发送监听列表

不同:

1、获取监听列表返回的已经是处理过的列表。

2、添加了@EventListener注解的自定义名称的方法,会在EventListenerMethodProcessor中的afterSingletonsInstantiated()方法中遍历所有 ApplicationContext容器的单利bean。将所有添加了@EventListener的方法注入到ApplicationContext的applicationListeners和 初始化的SimpleApplicationEventMulticasterdefaultRetriever.applicationListeners中,发送事件时候获取监听列表时用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值