使用Spring Event实现观察者模式

黄鹏宇 58 2024-01-10

一、依赖

  • spring-context
    由spring-boot-starter引入

二、 角色

  • 事件类:定义事件,继承ApplicationEvent的类成为一个事件类。
  • 发布者:发布事件(两种方式)
    1. 通过ApplicationContext发布事件,
    2. 实现ApplicationEventPublisherAware,通过ApplicationEventPublisher发布。
  • 监听者:监听并处理事件(两种方式)
    1. 实现ApplicationListener接口
    2. 使用@EventListener注解 (Spring4.2)

三、示例

1. 事件类

import org.springframework.context.ApplicationEvent;

public class CustomEvent extends ApplicationEvent {
    private String message;

    public CustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

2. 发布者


import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
public class TempPublisherService implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher publisher;
    private final ApplicationContext applicationContext;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    // publish方式1
    public void publish_1(String orderId) {
        log.info("购买订单:{}", orderId);
        // 发布事件
        applicationContext.publishEvent(new CustomEvent(this, orderId));
    }

    // publish方式2
    public void publish_2(String orderId) {
        log.info("购买订单:{}" , orderId);
        publisher.publishEvent(new CustomEvent(this, orderId));
    }
}

3. 监听者

3.1 方式一

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class CustomEventListener_1 implements ApplicationListener<CustomEvent> {
    @Override
    public void onApplicationEvent(CustomEvent event) {
        Object source = event.getSource();
        // 判断事件源是否是 TempPublisherService
        if (source instanceof TempPublisherService) {
            log.info("source is TempPublisherService");
        }

        log.info("source: {}", source);
        log.info("收到消息:{}", event.getMessage());
    }
}

3.2 方式二

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class CustomEventListener_2 {
    @EventListener({CustomEvent.class})
    public void onApplicationEvent(CustomEvent event) {
        log.info("收到消息:{}" , event.getMessage());
    }
}

4. 测试

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

import com.sdtlbco.cso.RunApplication;
import com.sdtlbco.cso.service.test.TempPublisherService;



@SpringBootTest(classes = RunApplication.class)
class ApplicationTests {
    @Resource
    private TempPublisherService tempPublisherService;

    @Test
    public void testPublisher_1() {
        tempPublisherService.publish_1("order_1");
    }

    @Test
    public void testPublisher_2() {
        tempPublisherService.publish_2("order_2");
    }
}

5. 输出

14:12:05:573[main][INFO][.c.s.t.TempPublisherService.25]: 购买订单:order_1
14:12:05:574[main][INFO][c.s.t.CustomEventListener_1.16]: source is TempPublisherService
14:12:05:575[main][INFO][c.s.t.CustomEventListener_1.19]: source: com.sdtlbco.cso.service.test.TempPublisherService@23e0c200
14:12:05:575[main][INFO][c.s.t.CustomEventListener_1.20]: 收到消息:order_1
14:12:05:576[main][INFO][c.s.t.CustomEventListener_2.13]: 收到消息:order_1
14:12:05:600[main][INFO][.c.s.t.TempPublisherService.32]: 购买订单:order_2
14:12:05:600[main][INFO][c.s.t.CustomEventListener_1.16]: source is TempPublisherService
14:12:05:601[main][INFO][c.s.t.CustomEventListener_1.19]: source: com.sdtlbco.cso.service.test.TempPublisherService@23e0c200
14:12:05:601[main][INFO][c.s.t.CustomEventListener_1.20]: 收到消息:order_2
14:12:05:602[main][INFO][c.s.t.CustomEventListener_2.13]: 收到消息:order_2