欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring中的观察者模式

程序员文章站 2022-06-28 19:28:51
一、Spring中观察者模式的四个角色 1.事件(ApplicationEvent) ApplicationEvent 是所有事件对象的父类。ApplicationEvent 继承自 jdk 的 EventObject, 所有的事件都需要继承 ApplicationEvent, 并且通过source ......

一、spring中观察者模式的四个角色

1.事件(applicationevent)

applicationevent 是所有事件对象的父类。applicationevent 继承自 jdk 的 eventobject, 所有的事件都需要继承 applicationevent, 并且通过source得到事件源。

下列描述了spring提供的内置事件:

  • contextrefreshedevent:事件发布在 applicationcontext 初始化或刷新时(例如:通过在 configurableapplicationcontext 接口使用refresh()方法)。这里,“初始化”意味着所有 bean 加载,post-processor bean 被检测到并且激活,单例预先实例化,applicationcontext 对象可以使用了。只要上下文没有关闭,可以触发多次刷新, applicationcontext 提供了一种可选择的支持这种“热”刷新。例如:xmlwebapplicationcontext 支持热刷新,但 genericapplicationcontext 并非如此。具体是在 abstractapplicationcontext 的 finishrefresh() 方法中。
  • contextstartedevent:事件发布在 applicationcontext 开始使用 configurableapplicationcontext 接口 start() 方法。这里,“开始”意味着所有生命周期 bean 接收到一个明确的起始信号。通常,这个信号用于明确停止后重新启动,但它也可以用于启动组件没有被配置为自动运行(例如:组件还没有开始初始化)。
  • contextstoppedevent:事件发布在 applicationcontext 停止时通过使用 configurableapplicationcontext 接口上的 stop() 方法。在这里,“停止”意味着所有生命周期bean接收一个显式的停止信号。停止上下文可以通过重新调用start()方法。
  • contextclosedevent:事件发布在 applicationcontext 关闭时通过关闭 configurableapplicationcontext 接口()方法。这里,“封闭”意味着所有单例 bean 被摧毁。一个封闭的环境达到生命的终结。它不能刷新或重启。
  • requesthandledevent:一个特定的web事件告诉所有能处理http请求的bean 。这个事件是在请求完成后发布的。这个事件只适用于使用 spring 的 dispatcherservlet 的web应用程序。

2.事件监听(applicationlistener)

applicationlistener 事件监听器,也就是观察者。继承自 jdk 的 eventlistener,该类中只有一个方法 onapplicationevent。当监听的事件发生后该方法会被执行。

3.事件发布(applicationcontext)

applicationcontext 是 spring 中的核心容器,在事件监听中 applicationcontext 可以作为事件的发布者,也就是事件源。因为 applicationcontext 继承自 applicationeventpublisher。在 applicationeventpublisher 中定义了事件发布的方法 — publishevent(object event)

4.事件管理(applicationeventmulticaster)

applicationeventmulticaster 用于事件监听器的注册和事件的广播。监听器的注册就是通过它来实现的,它的作用是把 applicationcontext 发布的 event 广播给它的监听器列表。

二、spring中实现观察者模式

  1. 自定义需要发布的事件类,需要继承 applicationevent 类或 payloadapplicationevent (该类也仅仅是对 applicationevent 的一层封装)
  2. 使用 @eventlistener 来监听事件或者实现 applicationlistener 接口。
  3. 使用 applicationeventpublisher 来发布自定义事件(@autowired注入即可)

@transactionaleventlistener 监听器:如果事件的发布不是在事务(@transactional)范围内,则监听不到该事件,除非将 fallbackexecution 标志设置为 true(@transactionaleventlistener(fallbackexecution = true));如果在事务中,可以选择在事务的哪个阶段来监听事件,默认在事务提交后监听(@transactionaleventlistener(phase = transactionphase.after_completion))。

以上介绍的事件监听都是同步,如果需要开启异步支持的话:

@configuration
@enableasync
public class asynceventconfiguration implements asyncconfigurer {
    @override
    public executor getasyncexecutor() {
        return executors.newcachedthreadpool();
    }
}

三、 实战

事件(myevent.java)

@component
public class myevent extends applicationevent {


    public myevent(applicationcontext source) {
        super(source);
        system.out.println("myevent 构造器执行");
    }

    public void echo() {
        system.out.println("模拟业务逻辑执行");
    }
}

事件监听(mylistenera.java、mylistenerb.java)

@component
public class mylistenera implements applicationlistener<myevent> {


    @override
    public void onapplicationevent(myevent myevent) {
        system.out.println("mylistenera");
        myevent.echo();
    }
}
@component
public class mylistenerb {
    
    @eventlistener
    public void onapplicationevent(myevent myevent) {
        system.out.println("mylistenerb");
        myevent.echo();
    }
    
}

事件发布(mypublisher.java)

@component
public class mypublisher implements applicationcontextaware {

    private applicationcontext applicationcontext;


    @override
    public void setapplicationcontext(applicationcontext applicationcontext) throws beansexception {
        this.applicationcontext = applicationcontext;
    }

    /**
     * 发布事件
     * 监听该事件的监听者都可以获取消息
     *
     * @param myevent
     */
    public void publisherevent(myevent myevent) {
        system.out.println("---开始发布 myevent 事件---");
        applicationcontext.publishevent(myevent);
    }
}

单元测试

@runwith(springrunner.class)
@springboottest
public class designpatternsapplicationtests {

    @autowired
    private mypublisher mypublisher;
    @autowired
    private myevent myevent;

    @test
    public void contextloads() {
        mypublisher.publisherevent(myevent);
    }
}

演示源代码 :https://github.com/jmcuixy/design-patterns/tree/master/src/main/java/com/example/observer/spring