我最近才开始尝试使用 Spring Roo。它在帮助人们快速构建具有集成持久性的域模型方面做得非常好。由于它在方面添加了持久性功能,我开始考虑以下问题:
Roo 在实际类/实体的一个方面添加了查找器(从数据库中加载满足可变条件的类的实例)。在 DDD 中,恕我直言,这是存储库的责任。存储库是显示在设计中的显式类。当然,作为一个方面,存储库功能隐藏在实体中并且几乎是不可见的。
所以这里有一个问题:一个切面是一个显式存储库类的真正替代品吗?Roo AOP 方法有什么缺点吗?
我最近才开始尝试使用 Spring Roo。它在帮助人们快速构建具有集成持久性的域模型方面做得非常好。由于它在方面添加了持久性功能,我开始考虑以下问题:
Roo 在实际类/实体的一个方面添加了查找器(从数据库中加载满足可变条件的类的实例)。在 DDD 中,恕我直言,这是存储库的责任。存储库是显示在设计中的显式类。当然,作为一个方面,存储库功能隐藏在实体中并且几乎是不可见的。
所以这里有一个问题:一个切面是一个显式存储库类的真正替代品吗?Roo AOP 方法有什么缺点吗?
从用户的角度来看,将查找器添加到您的域类感觉更自然,但它混合了您的层。Grails 通过添加静态 finder*() save(), ... 方法使用相同的方法。
除了美学之外,它在不用于 Web 应用程序设置时可能具有实际缺点:您的域类现在与您的数据库相关联。如果您通过 RMI 或 HttpInvoker 将这些对象传输到富客户端,则客户端不能并且通常可能不会使用 find* 方法,因为客户端上没有可用的会话/数据库连接。
我通常更喜欢允许域类引用服务层接口以防止贫血的域模型(http://martinfowler.com/bliki/AnemicDomainModel.html)。这有其自身的一系列缺点,但至少提供了一个明确的界限。在客户端上,服务接口背后的具体实现可以将所有方法调用代理到服务器(或者只使用带有 spring 远程处理或类似的同步代理)。
所以回答你的问题:它可能是一个替代品,但你应该意识到可能的负面后果,这会使你的域类(即你的核心业务逻辑)在系统之间的可移植性降低。
这取决于您的应用程序持久层的复杂程度以及您对它的控制程度。如果您的应用程序足够简单,可以通过JPA实现,那么这一切都可以通过 Roo 方面来处理。但是,如果您正在映射遗留表或需要高级数据库内容,那么您可能会发现自己处于Spring-JDBC是唯一出路的情况下,在这些情况下,存储库/dao 模型可能仍然有用。
我认为混合两种持久性模型在逻辑上是不一致的(并且是层责任的中断),因此我的大多数应用程序都需要这种高级数据库结构,因此我严格遵守存储库模型。
我认为将存储库方法添加到域对象是不好的设计。正确的位置是域类中的静态方法。但是域对象和它们的管理是两个不同的东西,应该分开。我更喜欢域对象和存储库。
我想动机是用 Java 实现 Rails/Grails 之类的东西。