public class Person {
//人员id
private String id;
//姓名
private String name;
//地址(值对象)
private Address address;
}
public class Address {
//省份
private String province;
//城市
private String city;
//街道
private String street;
}
# 值对象创建后不允许修改,只能用另外一个值对象来整体替换
# 值对象没有id,会被实体整体引用
- 案例一:值对象中只有一个属性
- 案例二:值对象中有多个属性,但只有一条记录的多属性值对象的实体
# 以上2种情况,将值对象的属性直接嵌入实体类
public class Person {
//人员id
private String id;
//姓名
private String name;
//省份
private String province;
//城市
private String city;
//街道
private String street;
}
- 当值对象中包含多个属性时,且会引用多条记录的多属性值对象的实体
# 以序列化大对象方式形成的实体对象,值对象则设计为Class类,值对象被序列化成大对象JSON串后,嵌入实体类中
public class Person {
//人员id
private String id;
//姓名
private String name;
//地址(值对象)
private Address address;
}
public class Address {
//省份
private String province;
//城市
private String city;
//街道
private String street;
}
# 领域建模时,将部分对象设计为值对象,保留对象的业务含义,同时又减少了实体数量
# 数据建模时,值对象的属性值和实体对象的属性值保存在同一DB实体表
# 由于领域建模与数据建模的区别,持久化操作前或持久化操作后需在共厂中转换
└── demo
├── application
| ├── event
| | ├── publish # 发布接口 + 实现
| | └── subscribe # 订阅接口 + 实现
| |
| └── service # 应用接口 + 实现
|
├── domain
| ├── aggregate1
| | ├── event # 存放事件实体,以及事件的具体业务逻辑实现
| | |
| | ├── model
| | ├── repository
| | └── service # 领域服务接口 + 实现
| |
| └── aggregate2
|
├── infrastructure
|
└── interfaces
# 个人理解:领域事件主要是用于跟踪已经发生的事,传递需要通知的消息,记录会引起其他模型对象改变状态的事件
# 例如使用rabbitmq进行发布和订阅消息
# <应用层中的event + 领域层中的event>写法与<应用服务 + 领域服务>类似
# 在两个微服务之间相互调用时,需要利用防腐层进行隔离
# 上游微服务 -> 防腐层(接口 + 实现) -> 下游微服务
# 这里的防腐层通常是我们使用的feign接口 + 实现
# 在防腐层中将上游数据模型转换为下游微服务所需的数据模型;例如在feign实现类中进行转换,参考chnx/cloud/seata01
# 防腐层往往属于下游限界上下文,用以隔绝上游限界上下文可能发生的变化
# 使用sentinel进行(异常、超时)降级
# 数据校验:对上游数据模型进行校验
# 接口防腐:将上游数据模型转为vo对象
# 防腐层之间不能进行调用(必须)
# 防腐层不允许有大量的业务逻辑,业务逻辑部分上提到调用端(必须):职责单一清晰
补充
# 防腐层个人认为放在application中