基于DDD的微服务落地

DDD四层架构

基于DDD的微服务落地

文章插图
DDD四层架构
对实时性要求高的强一致性业务场景 , 可采取分布式事务 。分布式事务有性能代价 , 在设计时需要平衡考虑业务拆分、数据一致性、性能和实现的复杂度 , 尽量避免分布式事务的产生 。
领域事件驱动的异步方式是分布式架构常用的设计方式 , 可以解决非实时性场景下的数据最终一致性问题 。基于消息中间件的领域事件发布和订阅 , 可以很好的解耦微服务 。通过削峰填谷 , 实现读写分离、减轻数据库实时访问压力 , 提高业务吞吐量和业务处理能力 。
DDD设计思想和方法
基于DDD的微服务落地

文章插图
DDD设计思想和方法
聚合根
聚合根包括聚合根属性、关联的实体和值对象以及自身的业务行为等 。通过引用实体和值对象 , 协调聚合内的多个实体 , 在聚合根类方法中完成多实体的复杂业务逻辑 。
充血模型:即领域模型模式 。有自己的业务行为(方法) , 如下充血模型中提供getDuration、addHistoryApprovalInfo等方法 。
贫血模型:即事务脚本模式 。只有对象属性和setter/getter 。
@Datapublic class Leave {String id;Applicant applicant;Approver approver;LeaveType type;Status status;Date startTime;Date endTime;long duration;//审批领导的最大级别int leaderMaxLevel;ApprovalInfo currentApprovalInfo;List<ApprovalInfo> historyApprovalInfos;public long getDuration() {return endTime.getTime() - startTime.getTime();}public Leave addHistoryApprovalInfo(ApprovalInfo approvalInfo) {if (null == historyApprovalInfos)historyApprovalInfos = new ArrayList<>();this.historyApprovalInfos.add(approvalInfo);return this;}public Leave create(){this.setStatus(Status.APPROVING);this.setStartTime(new Date());return this;}public Leave agree(Approver nextApprover){this.setStatus(Status.APPROVING);this.setApprover(nextApprover);return this;}public Leave reject(Approver approver){this.setApprover(approver);this.setStatus(Status.REJECTED);this.setApprover(null);return this;}public Leave finish(){this.setApprover(null);this.setStatus(Status.APPROVED);this.setEndTime(new Date());this.setDuration(this.getEndTime().getTime() - this.getStartTime().getTime());return this;}}实体
实体有自己的属性和关联的值对象 。
@Datapublic class ApprovalInfo {String approvalInfoId;Approver approver;ApprovalType approvalType;String msg;long time;}值对象
public enum Status {APPROVING, APPROVED, REJECTED}@Data@AllArgsConstructor@NoArgsConstructor@Builderpublic class Approver {String personId;String personName;int level;public static Approver fromPerson(Person person){Approver approver = new Approver();approver.setPersonId(person.getPersonId());approver.setPersonName(person.getPersonName());approver.setLevel(person.getRoleLevel());return approver;}}领域对象
如果一个业务行为由多个实体对象参与完成 , 就将该业务逻辑放在领域服务中实现 。
实体方法:完成单一实体自身的业务逻辑 , 是相对简单的原子业务逻辑 。
领域服务:由多个实体组合的相对复杂的业务逻辑 。
@Service@Slf4jpublic class LeaveDomainService {@AutowiredEventPublisher eventPublisher;@AutowiredILeaveRepository iLeaveRepository;@AutowiredLeaveFactory leaveFactory;@Transactionalpublic void createLeave(Leave leave, int leaderMaxLevel, Approver approver) {leave.setLeaderMaxLevel(leaderMaxLevel);leave.setApprover(approver);leave.create();iLeaveRepository.save(leaveFactory.createLeavePO(leave));LeaveEvent event = LeaveEvent.create(LeaveEventType.CREATE_EVENT, leave);iLeaveRepository.saveEvent(leaveFactory.createLeaveEventPO(event));eventPublisher.publish(event);}@Transactionalpublic void updateLeaveInfo(Leave leave) {LeavePO po = leaveRepositoryInterface.findById(leave.getId());if (null == po) {throw new RuntimeException("leave不存在");}iLeaveRepository.save(leaveFactory.createLeavePO(leave));}@Transactionalpublic void submitApproval(Leave leave, Approver approver) {LeaveEvent event;if ( ApprovalType.REJECT == leave.getCurrentApprovalInfo().getApprovalType()) {leave.reject(approver);event = LeaveEvent.create(LeaveEventType.REJECT_EVENT, leave);} else {if (approver != null) {leave.agree(approver);event = LeaveEvent.create(LeaveEventType.AGREE_EVENT, leave);} else {leave.finish();event = LeaveEvent.create(LeaveEventType.APPROVED_EVENT, leave);}}leave.addHistoryApprovalInfo(leave.getCurrentApprovalInfo());iLeaveRepository.save(leaveFactory.createLeavePO(leave));iLeaveRepository.saveEvent(leaveFactory.createLeaveEventPO(event));eventPublisher.publish(event);}public Leave getLeaveInfo(String leaveId) {LeavePO leavePO = iLeaveRepository.findById(leaveId);return leaveFactory.getLeave(leavePO);}public List<Leave> queryLeaveInfosByApplicant(String applicantId) {List<LeavePO> leavePOList = iLeaveRepository.queryByApplicantId(applicantId);return leavePOList.stream().map(leavePO -> leaveFactory.getLeave(leavePO)).collect(Collectors.toList());}public List<Leave> queryLeaveInfosByApprover(String approverId) {List<LeavePO> leavePOList = iLeaveRepository.queryByApproverId(approverId);return leavePOList.stream().map(leavePO -> leaveFactory.getLeave(leavePO)).collect(Collectors.toList());}}


推荐阅读