1)、继承 ApplicationListener 接口,实现 onApplicationEvent方法
在上一篇观察者模式-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和 初始化的SimpleApplicationEventMulticaster的defaultRetriever.applicationListeners中,在发送事件时候获取监听列表时用。