java观察者模式在spring中的应用_Spring源码之spring中的观察者模式和监听器的使用...

声明:本文根据鲁班学院子路老师spring中观察者模式课程整理得来

观察者模式特点:

被观察者持有监听的观察者的引用。

被观察者支持增加和删除的观察者。

被观察者状态改变通知观察者。

JDK中观察者implements Observer接口,重写update()方法

当观察者发生变化,收到通知进行具体的处理

可以随时取消

松耦合:

观察者增加或者删除无需修改被观察者的代码,只需调用被观察者对应的增加或则删除的方法即可

被观察者只负责通知观察者,但无需了解观察者如何处理通知

观察者只需等待被观察者通知,无需观察被观察者细节

通知不会错过:

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

Java实现

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

Java.util.Observable 这是一个类

java.util.Observer 这是一个接口

开关的重要性

可以筛选通知

可以撤销通知

可以控制通知

Spring中的观察者模式

在Spring中定义和应用程序上下文相关的事件时需要继承ApplicationEvent类

public abstract class ApplicationEvent extendsEventObject {/**use serialVersionUID from Spring 1.2 for interoperability.*/

private static final long serialVersionUID = 7099057708183571937L;/**System time when the event happened.*/

private final longtimestamp;/*** Create a new {@codeApplicationEvent}.

*@paramsource the object on which the event initially occurred or with

* which the event is associated (never {@codenull})*/

publicApplicationEvent(Object source) {super(source);this.timestamp =System.currentTimeMillis();

}/*** Return the system time in milliseconds when the event occurred.*/

public final longgetTimestamp() {return this.timestamp;

}

}

在ApplicationEvent的父类EventObject类(这个是java源码中的类)中有一个得到事件源的方法getSource()

901d2dbdb6bae4ea98834531c2a50330.png

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`。

676e85bc6f83a4fc918abfa946a1a0b1.png

以ContextStartedEvent这个类为例,实现SpringEvent的扩展功能,这个事件在context.start()的时候来进行监听处理。

public class ContextStartedEvent extendsApplicationContextEvent {/*** Create a new ContextStartedEvent.

*@paramsource the {@codeApplicationContext} that has been started

* (must not be {@codenull})*/

publicContextStartedEvent(ApplicationContext source) {super(source);

}

}

1.首先创建一个listener类

/*** spring通过实现ApplicationListener这个接口,同时传入一个泛型(ContextStartedEvent)就可以

* 监听到这个泛型对应的事件*/@Componentpublic class SpringListenerStart implements ApplicationListener{

@Overridepublic voidonApplicationEvent(ContextStartedEvent event) {

System.out.println("----- spring application start listener------");

}

}

2.创建测试类

public classTest {public static voidmain(String[] args) {

AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(WkApplication.class);

context.start();//在调用context的start()方法时,会触发spring的监听器,调用ContextStartedEvent对应的事件方法

}

}

3.运行结果

23fccc19cf6d17b67f40563ec773b947.png

Spring监听器的应用(模拟一个发邮件的监听器):

1.创建一个SpringMailEvent类,使它继承ApplicationEvent类(这个是Spring的事件类,自己的事件都要继承它)

public class SpringMailEvent extends ApplicationEvent implementsSerializable {//需要序列化,要不会报错。我也不知道为什么

private static final long serialVersionUID=762508508425139227l;privateString content;/*** Create a new {@codeApplicationEvent}.

*

*@paramsource the object on which the event initially occurred or with

* which the event is associated (never {@codenull})*/

publicSpringMailEvent(Object source) {super(source);

}publicString getContent() {returncontent;

}public voidsetContent(String content) {this.content =content;

}

}

2.创建一个SpringMailListener监听器类,使他实现ApplicationListener接口,同时泛型中穿我们自己定义的事件

@Componentpublic class SpringMailListener implements ApplicationListener{/*** 当程序调用了一个发邮件的方法时,这个监听器就会监听到,

* 同时在onApplicationEvent方法中做出响应

*@paramevent the event to respond to*/@Overridepublic voidonApplicationEvent(SpringMailEvent event) {

System.out.println("mail send ");

}

}

3.创建一个类,使自定义的监听器和事件与spring容器关联起来

/*** 创建自己的类,使自定义的监听器和事件与spring容器关联起来*/@Componentpublic classMailBean {

@Autowired

ApplicationContext context;//注入Sprig应用程序上下文/*** 我们之前只是定义了SpringMailEvent类,但是这个类并没有和Spring容器关联起来,

* 所以我们需要借助ApplicationContext的publishEvent()方法,把这个事件发布出去*/

public voidsendMail(){

context.publishEvent(newSpringMailEvent(context));

}

}

4.测试类

public classTest {public static voidmain(String[] args) {

AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(WkApplication.class);//context.start();//触发发邮件的事件

context.getBean(MailBean.class).sendMail();

}

}

5.测试结果

cf4eeeb77cfc7507e81da5159cc55a8a.png

2. **与request 请求相关联**

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

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)****将事件发送到已注册的监听器**。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值