使用spring框架提供的事件监听机制,实现观察者模式

1、spring事件监听机制介绍

Spring/ Spring Boot 提供了一套事件监听机制,可以实现观察者模式。涉及到的几个核心类和接口如下

1、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 主要的核心是类构造器,它可以初始化一个 source 事件关联对象,以便在事件监听器中获取并通知更新。

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

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
   void onApplicationEvent(E event);

}

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

3、 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 有一个默认接口方法和接口方法,接口方法需要由具体的子类实现。

4、 ApplicationContext
ApplicationContext 是 Spring 框架中的核心容器。ApplicationContext 接口继承了 ApplicationEventPublisher 接口,所以可以用 ApplicationContext 发布事件。

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    @Nullable
    String getId();

    String getApplicationName();

    String getDisplayName();

    long getStartupDate();

    @Nullable
    ApplicationContext getParent();

    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

使用的逻辑就是通过 ApplicationEventPublisher 或者 ApplicationContext 容器发布 ApplicationEvent 事件并关联事件对象,然后 ApplicationListener 监听该事件,当事件发布后,监听器就会收执行并获取到事件及关联对象。

2、使用spring事件监听机制实现观察者模式

1、新增被观察者

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

@Getter
public class TestEvent extends ApplicationEvent {


    public testEvent(Object source) {
        super(source);
    }


}

2、新增观察者

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

@RequiredArgsConstructor
public class TestListener implements ApplicationListener<TestEvent> {

    @NonNull
    private String result;

    @Async
    @Override
    public void onApplicationEvent(TestEvent event) {
        // 更新结果
        updateResult(event);
    }

    private void updateResult(TestEvent event) {
        this.result = (String) event.getSource();
        System.out.printf("result更新为:",  this.result );
    }

}

3、新增测试配置类

@Slf4j
@Configuration
public class ObserverConfiguration {

/**
CommandLineRunner 和 ApplicationRunner。他们的执行时机为容器启动完成的时候。
这两个接口中有一个 run 方法,我们只需要实现这个方法即可
*/
    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext context) {
        return (args) -> {
            log.info("发布事件:更新result?");
            context.publishEvent(new TestEvent("最新result"));
        };
    }

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

}

输出结果为:

result更新为:最新result

3、总结:

实际中的观察者模式应用应该应用于具体业务,比如电商支付场景,在用户支付完后可以发布一个支付事件,然后会有扣减积分,短信通知、赠送优惠券等一系列后续的事件监听器观察者,这样可以实现业务解耦。如果大家有用到消息中间件,其实也是观察者模式中发布订阅模式的概念。利用 Spring 中的事件监听机制可以轻松实现观察者模式,观察目标也不需要维护观察者列表了,相当于发布-订阅模式,它们之间是完全解耦的,需要注意的是每个观察者需要创建一个 Bean

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TheChainsmoker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值