如何将Repository与DDD和Spring集成

时间:2015-07-07 12:39:59

标签: java spring domain-driven-design ddd-repositories

我想使用Spring在DDD方法之后创建一个应用程序。假设我有一个商业模式类Foo和一个接口FooRepository

DDD告诉FooRepository的实施应该包含在基础设施层中。

我想使用CrudRepository,但如果我在域层中定义:

public interface FooRepository extends CrudRepository<Foo, Long>{
    // Some methods
}

我打破了核心概念,即域层(FooRepository接口)必须不知道基础架构层(CrudRepository)。

几个月前我读过这个领域驱动设计,但我还没有找到一个纯粹支持它的框架。

我怎么能以正确的方式做到这一点?

1 个答案:

答案 0 :(得分:1)

在分层架构中,您通常有3层:应用基础架构

基础设施

这里我把存储库的实现。在您的情况下,这是CrudRepository的实现,我将直接在具体类中实现,而不使用中间接口。我们对仓库中单个对象的行为方式做了 no 无论如何假设,我们只将它们放在那里并有效地检索它们。这样我们就不了解域名。我们只为域提供了一个与之交互的接口:WarehouseRepository的公共方法集。

public class WarehouseRepository implements CrudRepository<Foo, Long> {
    ...
}

当您在UnitOfWork / Transaction中时,模型的各个部分与WarehouseRepository交互。在方法adjustQuantityPlus中,我们只选择对应用程序不感兴趣的域逻辑,而不需要在基础结构级别知道。

public class SaleOrder {
    public adjustQuantityPlus(LineItemID lineItemID,
                              WarehouseRepository warehouseRepository) {
        this.lineItems.get(lineItemID).addOne(); //<-- add one to the order
        Product product = 
            warehouseRepository.findByLineItem(lineItem);
        product.minusOneFromStock(); //<-- decrease one from stock
    }
}

应用

这里我们启动和停止操作许多域对象的事务(UOWork)。每种业务方法都对应一个业务用例。

public class CustomerEventsManager {
    @Inject WarehouseRepository warehouseRepository;
    @Inject SaleOrderRepository saleOrderRepository;
    @Transactional
    public wantsOneMoreOf(ProductID productID, SaleOrderID saleOrderID) {
        SaleOrder saleOrder = 
            saleOrderRepository.findByID(saleOrderID)
        saleOrder.adjustQuantityPlus(productToLineItem(productID),
                                     warehouseRepository); //<-- add product
        webPage.showPromoDiscount(); //<-- show promotional advertisement
    }
}

上述代码是一项交易,如果系统无法将产品添加到订单中,我不想给客户打折。反过来,adjustQuantityPlus是一个带有域逻辑的内部“事务”,对应用程序层是隐藏的。