领域服务: 领域服务并不是应用服务,领域服务是无状态的,领域服务聚焦领域,领域服务设计不关注技术而聚焦于业务上下文
当值对象或者实体中的某个操作不在属于当前值对象或者领域对象的职责,那么应该抽取当前操作到领域服务并且保障领域服务的无状态性
哪些场景适合领域服务处理:
1 输入多个值对象或者实体进行业务处理
2 对领域对象进行转换
3 执行一个显著的业务过程
领域服务关注的是领域层:
领域服务本身实现可以衔接feign dao resttemplate rpc mq 等多种技术,但领域服务本身不是rpc或者mq
如果领域服务并没有过多的技术实现:比如微服务调用等
我们可以将其实现类直接放置于领域层并去除领域服务接口
备注:是实现类放置于领域层还是接口放置于领域层实现类放置于基础设施层,并无绝对优劣
如果无技术实现(feign,mybatis等),并且一个接口无相同实现类[业务],推荐使用实现类而去除接口;
备注2:防腐层往往起始于领域服务
领域事件:
其关注点是领域中发生的事件,领域事件需要继承公用类/接口来表示事件的发生时间等公用事件特点,领域事件的命名通常与其所在的领域以及业务行为相关,领域事件可以与领域实体设计于同一模块下的同一领域中
同时事件往往涉及到了发布方和订阅方
领域事件的发布由聚合/实体执行业务后创建事件并调用发布方发布事件
而订阅方往往由应用服务创建[有时候也通过领域服务创建]
举列如下
应用层
1创建订阅方,并注册到发布方
然后调用领域聚合执行业务
聚合发布业务执行完毕后的相关事件
【备注:代码有些粗糙,这里应该面向接口编程从而降低耦合】
public class DomainEventPublisher {
public static final ThreadLocal<List<DomainEventSubscriber>> subscribers = new ThreadLocal<>();
public static ThreadLocal<Boolean> publishing = new ThreadLocal<>();
public void publish(PostAuthorPostingEvent postAuthorPostingEvent){
List<DomainEventSubscriber> subscriber = subscribers.get();
subscriber.forEach(subscriber_ ->{
subscriber_.handle(postAuthorPostingEvent);
});
}
}
package com.dqdl.community.domain.model.subscriber;
import com.dqdl.community.domain.model.event.PostAuthorPostingEvent;
import java.util.List;
public class DomainEventSubscriber {
public void handle(PostAuthorPostingEvent postAuthorPostingEvent){
// 执行业务
// 调用领域服务
// 调用领域层repository
}
}
聚合代码
public class PostAuthor extends User{
private final static int MIN_LENGTH_POST_SOURCE_CONTENT = 16;
public PostAuthor(long id) {
super(id);
}
/**
* 发布帖子
* @param title
* @param sourceContent
* @return Post 发布得到的帖子
*/
public Post posting(String title, String sourceContent) throws BusinessException {
if(sourceContent.length() < MIN_LENGTH_POST_SOURCE_CONTENT) {
//抛出业务异常
throw new BusinessException(ReturnCode.POST_SOURCE_CONTENT_AT_LEAST_SIXTEEN_WORDS);
}
Post post = new Post(this.getId(), title, sourceContent);
DomainEventPublisher publisher = new DomainEventPublisher();
publisher.publish(new PostAuthorPostingEvent());
return post;
}
综上:不管是领域模型还是领域事件,我们都将关注点放置于领域这个概念层次,聚焦于领域并将技术实现抽离出领域层