Java中的领域事件模式实现?

7
我正在寻找一个简单的Java实现Udi Dahan领域事件模式和基础设施,如this article所述。
这很简单,我已经实现了自己的解释,但我是一个Java新手,不想因为对语言的经验不足而犯错误。
我发现的唯一的Java实现是在Jdon Framework中,但在我的项目中有点过于复杂。
谢谢!
2个回答

5

我已经在Java EE中寻找解决同样问题的方法有一段时间了。我看了Axonjdon(该页面实际上并不好 :))。两者都涉及事件溯源,这是我无法向我的雇主/客户“推销”的。虽然我非常习惯.NET/C#项目中的领域事件,但我仍然希望拥有领域事件。因此,我想到了以下解决方案...

我使用了类似的静态DomainEvents对象,以便为我提供访问发布机制的方式,而不会使实际实现细节泄漏到我的领域模型实体中。因此,调用类似这样的内容:

DomainEvents.fire(new MySampleEvent(...some params...));

CDI规范中可用的一种模式和机制是@Observes事件,它允许您使用所有服务来响应普通bean中的某些事件。这类似于我在使用诸如Castle Windsor之类的DI框架时注册通用处理程序接口的方式。所以我已经涵盖了观察者(处理程序、监听器或任何你想称呼它们的东西)。例如:
@Stateless
public class MySampleEventObserver {

  public void listen(@Observes MySampleEvent event) {
    ...
    doSomethingWithEvent();
  }
}

现在是发布(在CDI中触发)部分。由于无法访问实体中的CDI(理由充分!),因此我决定使用JNDI和BeanManager。我使用JNDI获取BeanManager并使用其fireEvent方法。将bean管理器解析(如这里所示)放入代码中:
public class BeanHelper {
  public static BeanManager getBeanManager() {
    try {
        InitialContext initialContext = new InitialContext();
        return (BeanManager) initialContext.lookup("java:comp/BeanManager");
    } catch (NamingException e) {
        e.printStackTrace();
        return null;
    }
  }

}

最后一步是 DomainEvents 对象本身:
public class DomainEvents {

  private static boolean mNopMode = false;

  public static void setNopMode() {
    mNopMode = true;
  }

  public static void reset() {
    mNopMode = false;
  }

  public static <TDomainEvent> void fire(TDomainEvent event) {
    if (mNopMode) {
        return;
    }
    BeanManager manager = BeanHelper.getBeanManager();

    manager.fireEvent(event);
  }

}

setNopModereset部分是为了在没有上下文的情况下进行测试。基本上是手动模拟。在单元测试之前将其设置为NOP操作模式,之后重置。

作为POC运行良好。不知道它的使用是否有任何严重限制。我将异步总线交互和类似的事情留给侦听器实现。

希望得到任何评论。


1

目前我正在考虑使用Google的Guava EventBus来实现类似于您参考文章中所提到的"救赎"的功能。

如果要使用类似于“如何引发领域事件”的方式来使用它,那么代码将会非常相似,几乎与该篇文章完全一致:

public class Customer
{
    public void DoSomething()
    {
        MyEventBus.post(new CustomerBecamePreferred() { Customer = this });
    }
}

我不知道你是否认为这是“Udi Dahan的领域事件模式”的实现。

它不需要实现任何接口;事件处理程序使用注释标记,并使用MyEventBus.register(aListenerObject)在EventBus中注册类。


谢谢Stephen,这很酷 - 我不知道Guava。我真的在努力让我的域与实现细节无关,但我会考虑使用Guava EventBus。也许我可以包装EventBus以隐藏实现细节。 - HolySamosa
是的 @HolySamosa - 我会在放置时进行包装,但保持简单的 register()post() 接口。 - Stephen P
我猜你会在你的领域模型中继续使用Guava Subscribe注解吗?我喜欢使用注解绑定订阅的想法,但我不愿意让这样的实现细节进入我的好看、干净的领域模型中。 - HolySamosa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接