本文探讨如下问题:
在EDA风格与Reactor模式一文中,我们从观察者模式聊到了EDA架构风格,然后聊了Reactor架构模式,最后以redis为例聊了Event-driven programming编程模式。
这些内容都是技术层面的,其共性是通过事件来进行解耦,提高系统的性能、扩展性、伸缩性、可运维性和灵活性。
而领域事件顾名思义也是通过事件来进行解耦,只是它是设计层面的技术。用于解耦领域设计中的组件:
在《领域驱动设计》的第七章,举了一个货运的例子。其中有个HandlingEvent,这就是一个事件对象。当货物被装货、卸货、密封、存放以及其他活动时就会创建一个HandlingEvent。
在这个例子中,是由人在货物被处理时,使用系统输入了一条HandlingEvent记录下来而已!而如果当发生了一个HandlingEvent后,需要后续的处理(比如发送通知给相关人员),该怎么办呢?这就是领域事件所要解决的问题!
在《领域驱动设计》中并没有提到领域事件,领域事件是其后出现的。
实际上,当出现类似如下关键词汇时,都可以考虑使用领域事件:
下面通过Spring的事件来实现上例中的具体流程。
public class HandlingEvent extends ApplicationEvent {
 private String actionName;
 public VisitEvent(Object source,String actionName) {
 super(source);
 this.actionName = actionName;
 }
}
@Service@EnableAsyncpublic class EventPublisher implements ApplicationEventPublisherAware {
 private ApplicationEventPublisher publisher;
 @Override
 public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
 this.publisher = applicationEventPublisher;
 }
 public void publish(ApplicationEvent event) {
 publisher.publishEvent(event);
 }
}
@Componentpublic class HandlingListener {
 @EventListener
 @Async("eventThread")
 public void processHandlingEvent(HandlingEvent event) {
 // 处理事件
 }
eventPublisher.publish(new HandlingEvent(this, "move"));
整体的流程如下:
我们看下Spring中如何实现这个流程的。
for (Method method : annotatedMethods.keySet()) {
 for (EventListenerFactory factory : factories) {
 if (factory.supportsMethod(method)) {
 Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
 ApplicationListener<?> applicationListener =
 factory.createApplicationListener(beanName, targetType, methodToUse);
 if (applicationListener instanceof ApplicationListenerMethodAdapter) {
 ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
 }
 context.addApplicationListener(applicationListener);
 break;
 }
 }
}
@Overridepublic void addApplicationListener(ApplicationListener<?> listener) {
 Assert.notNull(listener, "ApplicationListener must not be null");
 if (this.applicationEventMulticaster != null) {
 this.applicationEventMulticaster.addApplicationListener(listener);
 }
 this.applicationListeners.add(listener);
}
ApplicationContext接口为什么要继承ApplicationEventPublisher接口?
因为Spring中定义了几个默认的事件ContextRefreshedEvent,ContextStartedEvent,ContextStoppedEvent,ContextClosedEvent,RequestHandledEvent,而ApplicationContext就是这些事件的布者。
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
 ......
 else {
 getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); // 广播事件
 }
 .....
}
@Overridepublic void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
 ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
 for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
 Executor executor = getTaskExecutor();
 if (executor != null) {
 executor.execute(() -> invokeListener(listener, event));
 }
 else {
 invokeListener(listener, event);
 }
 }
}
原文:https://www.cnblogs.com/ivaneye/p/14117353.html