Spring的事件机制

Posted by Static on May 5, 2021

1. What?

Spring的ApplicationEventPublisher拥有事件发布并且注册事件监听器的能力,拥有一套完整的事件发布与监听机制,类似于Guava的EventBus。


2. Why?

事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现,高类聚低耦合,降低业务代码的耦合度,支持异步操作。


3. How?

核心类:

a. 事件ApplicationEvent;

b. 事件发布者ApplicationEventPublisher;

c. 事件监听器ApplicationListener或注解@EventListener


步骤:

1.创建自定义的事件模型

@Data
public class Something {
    // 自定义字段
    private String id;
    private String type;
    private String name;
    // ...
}

2.自定义事件继承ApplicationEvent

public class SomethingRegisterEvent extends ApplicationEvent{
    public SomethingRegisterEvent(Something something) {
        super(something);
    }
}

3.创建事件发布者

@Service
@Slf4j
public class EventService {

    @Autowired
    private ApplicationEventPublisher publisher;

    public void publishSomething(Something something) {
        publisher.publishEvent(new SomethingRegisterEvent(something));
        log.info("EventService->publishSomething publish success,something:{}", something);
    }
}

4.添加事件监听器

a.实现接口方式

@Component
@Slf4j
public class SomethingAsyncEventListener implements ApplicationListener<SomethingRegisterEvent> {

    @Override
    // 通过自定义线程池实现异步
    @Async("commonExecutorPool")
    public void onApplicationEvent(@NonNull SomethingRegisterEvent somethingRegisterEvent) {
        Something something = (Something) somethingRegisterEvent.getSource();
        handlerSomething(something);
        log.info("SomethingAsyncEventListener->onApplicationEvent success");
    }

    private void handlerSomething(Something something) {
        log.info("SomethingAsyncEventListener->handler something:{}", something);
    }

}

b.通过注解实现

@Component
@Slf4j
public class SomethingEventOneListener {
    @EventListener(value = SomethingRegisterEvent.class, condition = "#event.source.type=='opt'")
    public void firstHandler(SomethingRegisterEvent event) {
        log.info("SomethingEventOneListener->firstHandler success,event:{}", event);
    }

    @EventListener(value = SomethingRegisterEvent.class, condition = "#event.source.type=='opt'")
    // 通过自定义线程池实现异步
    @Async("commonExecutorPool")
    public void secondHandler(SomethingRegisterEvent event) {
        log.info("SomethingEventOneListener->secondHandler success,event:{}", event);
    }
}

可通过自定义状态机实现策略模式;线程池实现:传送门

5.测试

@SpringBootTest(classes = {SpringBootDemoApplication.class})
@RunWith(SpringRunner.class)
public class EventServiceTest {
    @Autowired
    private EventService eventService;

    @Test
    public void test() {
        Something something = new Something();
        something.setId("0");
        something.setName("test");
        something.setType("opt");
        eventService.publishSomething(something);

    }
}