乐趣区

关于java:别再面向-for-循环编程了Spring-自带的观察者模式就很香

上一篇:JDK 自带的观察者模式就很香!

前段时间栈长给大家分享了什么是观察者模式,以及在 JDK 中如何实现观察者模式,当初都是 Spring 的天下了,明天就再分享下如何在 Spring/ Spring Boot 中实现观察者模式。

不必再面试 for 循环编程了,Spring 框架自带的事件监听机制,实现观察者模式、实现解耦轻松帮你全搞定!

Spring 事件监听机制

其实在 Spring/ Spring Boot 框架中有一套事件监听机制,能够实现观察者模式。

Spring/ Spring Boot 框架中也都内置了许多事件,咱们也能够自定义公布应用程序事件,上面咱们会介绍。

其次要波及到的几个外围类和接口如下:

ApplicationEvent

ApplicationEvent(应用程序事件)它是一个抽象类,相当于观察者模式中的察看指标。

ApplicationEvent 源码如下:

public abstract class ApplicationEvent extends EventObject {

   /** use serialVersionUID from Spring 1.2 for interoperability. */
   private static final long serialVersionUID = 7099057708183571937L;

   /** System time when the event happened. */
   private final long timestamp;


   /**
    * Create a new {@code ApplicationEvent}.
    * @param source the object on which the event initially occurred or with
    * which the event is associated (never {@code null})
    */
   public ApplicationEvent(Object source) {super(source);
      this.timestamp = System.currentTimeMillis();}


   /**
    * Return the system time in milliseconds when the event occurred.
    */
   public final long getTimestamp() {return this.timestamp;}

}

ApplicationEvent 继承自 Java 中的 EventObject 事件对象类,Spring 框架中的所有事件都继承自 ApplicationEvent 类,它是所有事件的父类。

ApplicationEvent 次要的外围是类结构器,它能够初始化一个 source 事件关联对象,以便在事件监听器中获取并告诉更新。

ApplicationListener

ApplicationListener(应用程序事件监听器)它是一个接口,相当于观察者模式中的观察者。

ApplicationListener 源码如下:

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

   /**
    * Handle an application event.
    * @param event the event to respond to
    */
   void onApplicationEvent(E event);

}

ApplicationListener 继承自 Java 中的 EventListener 事件监听接口,ApplicationListener 类中只有一个 onApplicationEvent 办法,当指定监听的事件被公布后就会被触发执行,能够通过 event 获取事件中的关联对象。

ApplicationEventPublisher

应用程序事件公布接口,封装了事件公布性能的根底接口。

public interface ApplicationEventPublisher {

   /**
    * Notify all <strong>matching</strong> listeners registered with this
    * application of an application event. Events may be framework events
    * (such as ContextRefreshedEvent) or application-specific events.
    * <p>Such an event publication step is effectively a hand-off to the
    * multicaster and does not imply synchronous/asynchronous execution
    * or even immediate execution at all. Event listeners are encouraged
    * to be as efficient as possible, individually using asynchronous
    * execution for longer-running and potentially blocking operations.
    * @param event the event to publish
    * @see #publishEvent(Object)
    * @see org.springframework.context.event.ContextRefreshedEvent
    * @see org.springframework.context.event.ContextClosedEvent
    */
   default void publishEvent(ApplicationEvent event) {publishEvent((Object) event);
   }

   /**
    * Notify all <strong>matching</strong> listeners registered with this
    * application of an event.
    * <p>If the specified {@code event} is not an {@link ApplicationEvent},
    * it is wrapped in a {@link PayloadApplicationEvent}.
    * <p>Such an event publication step is effectively a hand-off to the
    * multicaster and does not imply synchronous/asynchronous execution
    * or even immediate execution at all. Event listeners are encouraged
    * to be as efficient as possible, individually using asynchronous
    * execution for longer-running and potentially blocking operations.
    * @param event the event to publish
    * @since 4.2
    * @see #publishEvent(ApplicationEvent)
    * @see PayloadApplicationEvent
    */
   void publishEvent(Object event);

}

ApplicationEventPublisher 有一个默认接口办法和接口办法,接口办法须要由具体的子类容器实现。

ApplicationContext

ApplicationContext 这个类就再相熟不过了,它是 Spring 框架中的外围容器。

如下图所示,ApplicationContext 接口继承了 ApplicationEventPublisher 接口,所以罕用的 ApplicationContext 就能够用来公布事件。

以上介绍的 Spring 事件监听公布角色串起来就是,通过 ApplicationEventPublisher 或者 ApplicationContext 容器公布 ApplicationEvent 事件并关联事件对象,而后 ApplicationListener 监听该事件,当事件公布后,监听器就会收执行并获取到事件及关联对象。

Spring Boot 观察者模式实战

搞懂了 Spring 框架中的事件和监听机制,那咱们还是以上篇中观察者模式的例子来革新下。

Spring Boot 基础性的常识和搭建过程就不介绍了,不相熟的能够关注公众号 Java 技术栈,在后盾回复关键字 “boot” 浏览我之前写的系列教程。

所有 Spring Boot 教程实战源码在上面个仓库:

https://github.com/javastacks…

新增观察者指标类

import lombok.Getter;
import org.springframework.context.ApplicationEvent;

/**
 * 察看指标:栈长
 * 起源微信公众号:Java 技术栈
 */
@Getter
public class JavaStackEvent extends ApplicationEvent {

    /**
     * Create a new {@code ApplicationEvent}.
     *
     * @param source the object on which the event initially occurred or with
     *               which the event is associated (never {@code null})
     */
    public JavaStackEvent(Object source) {super(source);
    }


}

实现 Spring 框架中的 ApplicationEvent 应用程序事件接口,相当于是一个观察者指标。

新增观察者类

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;

/**
 * 观察者:读者粉丝
 * 起源微信公众号:Java 技术栈
 */
@RequiredArgsConstructor
public class ReaderListener implements ApplicationListener<JavaStackEvent> {

    @NonNull
    private String name;

    private String article;

    @Async
    @Override
    public void onApplicationEvent(JavaStackEvent event) {
        // 更新文章
        updateArticle(event);
    }

    private void updateArticle(JavaStackEvent event) {this.article = (String) event.getSource();
        System.out.printf("我是读者:%s,文章已更新为:%s\n", this.name, this.article);
    }

}

实现 Spring 框架中的 ApplicationListener 利用监听接口,相当于是观察者。

察看指标和观察者类结构图如下:

新增测试配置类

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Slf4j
@Configuration
public class ObserverConfiguration {

    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext context) {return (args) -> {log.info("公布事件:什么是观察者模式?");
            context.publishEvent(new JavaStackEvent("什么是观察者模式?"));
        };
    }

    @Bean
    public ReaderListener readerListener1(){return new ReaderListener("小明");
    }

    @Bean
    public ReaderListener readerListener2(){return new ReaderListener("小张");
    }

    @Bean
    public ReaderListener readerListener3(){return new ReaderListener("小爱");
    }

}

在 Spring 配置中创立了三个读者 Bean,在 Spring Boot 启动后公布一个观察者模式事件,而后这三个 Bean 就会收到告诉。

输入后果:

这里每个读者创立一个 Bean 可能不太适合,因为要模拟上一个观察者模式的利用。

理论中的观察者模式利用应该是指具体业务,举例说一个电商领取场景,在用户领取完后能够公布一个领取事件,而后会有扣减积分,短信告诉、赠送优惠券等一系列后续的事件监听器观察者,这样能够实现业务解耦,这是一种很典型的利用场景。

如果大家有用到消息中间件,其实也是观察者模式中公布订阅模式的概念。

总结

利用 Spring 中的事件监听机制也能够轻松实现观察者模式,察看指标也不须要保护观察者列表了,相当于公布 - 订阅模式,它们之间是齐全解耦的,但每个观察者须要创立一个 Bean。

好了,明天的分享就到这里了,又学了一种设计模式的写法吧,前面栈长我会更新其余设计模式的实战文章,公众号 Java 技术栈第一工夫推送。

本节教程所有实战源码已上传到这个仓库:

https://github.com/javastacks…

最初,感觉我的文章对你用播种的话,动动小手,给个在看、转发,原创不易,栈长须要你的激励。

版权申明:本文系公众号 “Java 技术栈 ” 原创,原创实属不易,转载、援用本文内容请注明出处,禁止剽窃、洗稿,请自重,尊重别人劳动成果和知识产权。

近期热文举荐:

1.600+ 道 Java 面试题及答案整顿 (2021 最新版)

2. 终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!

3. 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!

5.《Java 开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞 + 转发哦!

退出移动版