同步操作将从 李晓静/EasyDomain 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
领域模型实用库是为领域驱动开发设计的基础类库,主要包括实体对象通用能力支持、基于实体的业务规则验证支持、领域事件支持以及应用服务层基于领域事件的发布订阅模式支持。
编辑您的pom.xml文件
<profiles>
<profile>
<id>coding</id>
<repositories>
<repository>
<id>leebmw-easy-snapshoot</id>
<name>snapshoot</name>
<url>https://leebmw-maven.pkg.coding.net/repository/easy/snapshoot/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
<dependency>
<groupId>easy.ddd.domain</groupId>
<artifactId>easy-domain</artifactId>
<version>1.1</version>
</dependency>
根据领域驱动设计中实体的定义,一个实体是一个唯一的东西,每一个实体都有一个唯一的业务身份标识,并且实体具有生命周期,在生命周期内实体的状态会不断发生变化。实体对象的每一次变化都需要使用业务规则进行验证,以保证实体状态的变更是合法有效的。
实体的通用基类 EntityBase 和 ConcurrentEntityBase。
class Order extends EntityBase<Long> {
@Override
public Boolean validate() {
return null;
}
@Override
protected BrokenRuleMessage getBrokenRuleMessages() {
return null;
}
}
class Order extends ConcurrentEntityBase<Long> {
@Override
public Boolean validate() {
return null;
}
public BrokenRuleMessage getBrokenRuleMessages() {
return null;
}
}
实体具有唯一的身份标识,在生命周期内实体的状态会不断发生变化,实体业务规则类,负责保证在实体对象状态变化的过程中实体数据合法有效,当有异常数据时,能够反馈出异常数据的描述或具体异常字段信息等。
业务规则类的基类 EntityRule
class OrderEntityRule extends EntityRule<Order> {
// 1
public OrderEntityRule() {
// 2
this.isBlank("pin", OrderBrokenRuleMessages.PIN_IS_EMPTY, "");
// 3
this.addRule("totalPrice", new IRule<Order>() {
@Override
public boolean isSatisfy(Order model) {
return model.getTotalPrice().compareTo(BigDecimal.ZERO) > 0;
}
}, OrderBrokenRuleMessages.TOTAL_PRICE_ERROR, "");
// 4
this.addRule(new IRule<Order>() {
@Override
public boolean isSatisfy(Order model) {
// 4.1
return model.getOrderItemList().size() > 0 && model.getOrderItemList().size() < 100;
}
}, OrderBrokenRuleMessages.ORDER_ITEM_ERROR, "", new IActiveRuleCondition<Order>() {
// 4.2
@Override
public boolean isActive(Order model) {
return model.getStatus() == 1;
}
});
}
}
// 5
class OrderBrokenRuleMessages extends BrokenRuleMessage {
// 5.1
public static final String PIN_IS_EMPTY = "PIN_IS_EMPTY";
public static final String TOTAL_PRICE_ERROR = "TOTAL_PRICE_ERROR";
public static final String ORDER_ITEM_ERROR = "ORDER_ITEM_ERROR";
@Override
protected void populateMessage() {
// 5.2
this.getMessages().put(PIN_IS_EMPTY, "用户PIN不能为空");
this.getMessages().put(TOTAL_PRICE_ERROR, "订单总金额不能为0");
this.getMessages().put(ORDER_ITEM_ERROR, "订单商品不能为0且商品数超过100");
}
}
class Order extends EntityBase<Long> {
// 1
@Override
public Boolean validate() {
// 1.1
return new OrderEntityRule().isSatisfy(this);
}
// 2
@Override
protected BrokenRuleMessage getBrokenRuleMessages() {
// 2.2
return new OrderBrokenRuleMessages();
}
}
实体业务规则验证,需要和实体配合一块使用,以实体为中心展开验证,一般一个实体只对应一个实体业务规则EntityRule
在实体类中重写validate()方法,如以上示例中 1.1显示,也可以自行写一个validate()的重载,以便实现更加灵活的EntityRule类管理。
在实体类中,还需要重写getBrokenRuleMessages(),直接返回实体业务规则异常描述类的一个实例,如以上的 2.2,一般情况下,实体业务规则异常描述类,是线程安全的,因此,也可以定义单例模式,在getBrokenRuleMessages()方法中返回单例对象。
public class MainTestClass {
@Test
public void orderTest() {
// 3
Order order = new Order();
// 4
Boolean validate = order.validate();
if (!validate) {
// 5
order.getBrokenRules();
// 6
order.aggregateExceptionCause();
// 7
order.throwBrokeRuleAggregateException();
// 8
order.exceptionCause();
// 9
order.throwBrokenRuleException();
}
}
}
在领域驱动设计中,领域事件是对实体对象,由于某一业务操作导致实体对象状态发生变化的事实的描述。例如,当订单实体调用支付payment() 方法后,订单的状态变成已支付,并产生订单已支付的事件,该事件将交由应用服务层去发布,相关业务组件将会订阅订单已支付事件、并对事件做出相关的响应。
@EventName(value = "OrderPayedEvent", shareTopicName = "")
class OrderPayedEvent extends BaseDomainEvent {
//还可以有其他的字段
public OrderPayedEvent(long orderId) {
this.setBusinessId(String.valueOf(orderId));
}
}
class Order extends EntityBase<Long> {
private BigDecimal totalPrice = BigDecimal.ZERO;
private String comment = "";
private String pin;
private int status;
private List<OrderItem> orderItemList;
@Override
public Boolean validate() {
return new OrderEntityRule().isSatisfy(this);
}
@Override
protected BrokenRuleMessage getBrokenRuleMessages() {
return new OrderBrokenRuleMessages();
}
/**
* 订单支付业务操作
*
* @return 返回订单已支持事件
*/
public OrderPayedEvent payment() {
this.status = 3;
return new OrderPayedEvent(this.getId());
}
}
应用服务层,在领域驱动设计分层架构中的角色是用于实现协作、统筹和编排领域模型以及基础设施层的各种业务组件类,以实现相关业务功能。此外,对实体对象的各种操作,都必须经由应用服务层处理,任何其它地方都不能私自处理。应用服务层,也是用于保证实体对象逻辑一致性(强一致,一般指数据库事务)和发布实体对象生成的领域事件的地方。
应用服务层是极容易出现代码坏味道的地方,应用服务层是协作者,不是业务决策者。在该层出现业务决策类的代码段时,需要格外注意。
通过将业务决策代码放回到领域层以及通过发布订阅模式将各业务组件进行解耦,可以使该层清晰职责和结构。
// 1
class OrderApplicationService extends BaseApplication {
private IOrderRepository orderRepository;
// 2
public OrderApplicationService() {
this.initSubscriber();
}
public void payment(long orderId) {
// 3
Order order = this.orderRepository.findByOrderId(orderId);
if (order != null) {
// 4
OrderPayedEvent orderPayedEvent = order.payment();
// 5
if (order.validate()) {
// 6
this.orderRepository.update(order);
// 7
this.publishEvent(orderPayedEvent);
} else {
// 8
throw order.exceptionCause();
}
}
}
}
class OrderApplicationService extends BaseApplication {
private IOrderRepository orderRepository;
public OrderApplicationService() {
// 1
this.initSubscriber();
}
public void payment(long orderId) {
//发布OrderPayedEvent事件
}
private void initSubscriber() {
// 2
this.registerDomainEvent(OrderPayedEvent.class);
// 3
this.registerSubscriber(new IDomainEventSubscriber<OrderPayedEvent>() {
@Override
public Class<OrderPayedEvent> subscribedToEventType() {
return OrderPayedEvent.class;
}
@Override
public void handleEvent(OrderPayedEvent aDomainEvent) {
//调用发送通知用户支付成功的消息服务
}
}, "sendSMS");
// 4
this.registerSubscriber(new IDomainEventSubscriber<OrderPayedEvent>() {
@Override
public Class<OrderPayedEvent> subscribedToEventType() {
return OrderPayedEvent.class;
}
@Override
public void handleEvent(OrderPayedEvent aDomainEvent) {
//调用通知库房准备生产服务领域事件对上的注解
}
}, "noticeWarehouse");
}
}
在领域驱动设计中,基础设施层提供具体技术上的支撑,实体对象数据的数据库持久化,面向查询的数据持久化(ES)、面向缓存的数据刷新(Redis)、外部系统远程接口调用以及发布供外部系统处理的消息等。 基础设施层主要有以下几个特点
class OrderRepository implements IOrderRepository {
@Override
public Order findByOrderId(long orderId) {
//执行数据库查询,返回领域模型对象
return null;
}
@Override
public void update(Order order) {
// 1
// 持久化领域模型数据
}
}
领域驱动设计,将一个系统或微服务划分成四层,每一层都是不同的角色,有不同的职责。
上图蓝色线体现了各层之间的调用关系,各层的调用并不会严格的经过每一层。
图中所示的另一个调用分别经过了,应用服务层、领域模型层和基础设施层,这种情况一般是,一个业务操作,需要对领域模层的实体进行变更,应用服务层需要装载实体对象数据到内存,然后调用实体对象上的业务方法,接下来执行业务规则验证,通过后,调用基础设施层进行相关持久操作等。
上图红色线体现了基础设施层和各层之间的依赖关系。
领域模型是整个系统的核心和灵魂,所有其它方面都会围绕领域模型开展。当我们需要了解一个系统的时候 ,一般也会从领域模型做为开端。
以MyBatis的写法为例,保存订单数据到数据库
UPDATE order
SET status=1,
version=#{order.newVersion}
WHERE order_id = #{order.id}
AND version = #{order.oldVersion}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。