一、背景篇
在软件开发领域,随着业务需求的不断增长和复杂化,传统的单体架构逐渐暴露出扩展性差、维护困难等问题。
为了应对这些挑战,微服务架构应运而生。微服务架构的核心思想是"分而治之",就是将一个大型系统拆分成多个独立的小型服务,每个服务专注于一个特定的业务功能。这种拆分方式带来了许多好处,如更高的灵活性、更好的扩展性和更快的开发速度。
然而,随着微服务的广泛应用,一些问题也逐渐显现出来:
- 服务爆炸:微服务拆分过细,导致服务数量急剧增加,管理和维护成本也随之上升。
- 拆分不合理:服务拆分不合理,导致服务之间的耦合度过高,频繁的重构和调整成为常态。
- 数据一致性:微服务之间的数据一致性问题变得更加复杂,尤其是在分布式系统中。
为了解决这些问题,领域驱动设计(Domain-Driven Design,简称DDD)又实重新激活。这里说的是"激活",我们知道 DDD 并不是最近出有的,最初 DDD 是由Eric Evans在2003年提出的。由于它比较复杂,当时行业发展程度、面临的问题也都还不合适,所以并没有流行起来。

二、理论篇
2.1、DDD 的核心概念

- 领域(Domain)
领域是业务的核心,包含了业务规则、业务实体、业务流程等。在 DDD 中,领域是软件设计的核心,所有的设计决策都应该围绕领域进行。 - 子域(Subdomain)
子域是领域的一部分,通常对应于业务中的一个特定功能或模块。例如,在一个电商系统中,订单管理、用户管理、库存管理等都可以看作是不同的子域。 - 实体(Entity)
实体是具有唯一标识的对象,它们的生命周期跨越多个业务操作。实体通常包含业务逻辑和状态。 - 值对象(Value Object)
值对象是没有唯一标识的对象,它们通常用于表示业务概念中的值与前端交互。 - **聚合(Aggregate)
**聚合是一组相关实体和值对象的集合,它们作为一个整体进行操作。聚合根(Aggregate Root)是聚合的入口点,负责维护聚合内部的一致性。 - 领域服务(Domain Service)
领域服务用于封装不属于任何实体或值对象的业务逻辑。 - **领域事件(Domain Event)
**领域事件用于表示领域中发生的特定事件。通过发布和订阅领域事件,可以实现业务逻辑的解耦和系统的扩展。 - **仓储(Repository)
**仓储用于封装数据访问逻辑,提供对聚合的持久化和查询操作。仓储通常是接口,具体的实现放在基础设施层。 - 反腐层(Anti-Corruption Layer)
反腐层用于保护领域模型不受外部模型的影响,确保领域模型的纯洁性。
2.2、DDD 的四层架构

用户界面层(Interface)
负责处理用户交互,通常包括控制器(Controller)、视图(View)等组件。
应用层(Application)
定义系统的用例(Use Cases),但不包含具体的业务逻辑。应用层通常依赖于领域层来完成具体的业务操作。
领域层(Domain)
包含业务逻辑、业务实体、值对象、领域服务、聚合、仓储接口等。领域层是业务规则和业务逻辑的实现地。
基础设施层(Infrastructure)
提供技术支持,包括数据持久化、消息传递、外部服务调用等。基础设施层通常实现领域层中的仓储接口,并提供具体的持久化实现。
三、实战篇
系统业务功能包含用户和角色,功能比较简单,就是用户和角色创建、修改、删除。下面就一步步来实现
1、项目结构
csharp
com
└── company
└── um
├── ddd-infrastructure
│ ├── dao
│ │ ├── UserDAO.java
│ │ └── RoleDAO.java
│ ├── repository
│ │ ├── UserRepository.java
│ │ └── RoleRepository.java
│ └── mapper
│ ├── UserMapper.java
│ └── RoleMapper.java
├── ddd-domain
│ ├── entity
│ │ ├── User.java
│ │ └── Role.java
│ ├── factory
│ │ └── UserFactory.java
│ ├── service
│ │ └── RoleAssignmentService.java
│ ├── event
│ │ └── UserCreatedEvent.java
│ └── exception
│ └── DomainException.java
├── ddd-application
│ ├── service
│ │ ├── UserService.java
│ │ └── RoleService.java
│ └── dto
│ ├── UserDTO.java
│ └── RoleDTO.java
└── ddd-interface
├── controller
│ └── UserController.java
└── vo
├── UserVO.java
└── RoleVO.java
2、代码实现
1. 基础设施层 (ddd-infrastructure)
1.1 数据访问对象 (DAO)
UserDAO.java
csharp
public interface UserDAO {
void save(User user);
User findById(Long id);
void delete(User user);
}
RoleDAO.java
csharp
public interface RoleDAO {
void save(Role role);
Role findById(Long id);
void delete(Role role);
}
1.2 仓库 (Repository)
UserRepository.java
java
public interface UserRepository {
void save(User user);
User findById(Long id);
void delete(User user);
}
@Repository
public class UserRepositoryImpl implements UserRepository {
@Autowired
private UserDAO userDAO;
public void save(User user) {
userDAO.save(user);
}
public User findById(Long id) {
return userDAO.findById(id);
}
public void delete(User user) {
userDAO.delete(user);
}
}
RoleRepository.java
java
public interface RoleRepository {
void save(Role role);
Role findById(Long id);
void delete(Role role);
}
@Repository
public class RoleRepositoryImpl implements RoleRepository {
@Autowired
private RoleDAO roleDAO;
public void save(Role role) {
roleDAO.save(role);
}
public Role findById(Long id) {
return roleDAO.findById(id);
}
public void delete(Role role) {
roleDAO.delete(role);
}
}
1.3 映射器 (Mapper)
UserMapper.java
java
public interface UserMapper {
UserDTO toDTO(User user);
User toEntity(UserDTO userDTO);
}
@Component
public class UserMapperImpl implements UserMapper {
public UserDTO toDTO(User user) {
UserDTO userDTO = new UserDTO();
userDTO.setId(user.getId());
userDTO.setName(user.getName());
// 其他属性映射
return userDTO;
}
public User toEntity(UserDTO userDTO) {
User user = new User();
user.setId(userDTO.getId());
user.setName(userDTO.getName());
// 其他属性映射
return user;
}
}
RoleMapper.java
java
public interface RoleMapper {
RoleDTO toDTO(Role role);
Role toEntity(RoleDTO roleDTO);
}
@Component
public class RoleMapperImpl implements RoleMapper {
public RoleDTO toDTO(Role role) {
RoleDTO roleDTO = new RoleDTO();
roleDTO.setId(role.getId());
roleDTO.setName(role.getName());
// 其他属性映射
return roleDTO;
}
public Role toEntity(RoleDTO roleDTO) {
Role role = new Role();
role.setId(roleDTO.getId());
role.setName(roleDTO.getName());
// 其他属性映射
return role;
}
}
2. 领域层 (ddd-domain)
2.1 实体 (Entity)
User.java
typescript
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Set<Role> roles = new HashSet<>();
// 构造器、getter、setter 省略
public void addRole(Role role) {
roles.add(role);
role.setUser(this);
}
public void removeRole(Role role) {
roles.remove(role);
role.setUser(null);
}
}
Role.java
kotlin
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
// 构造器、getter、setter 省略
public void setUser(User user) {
this.user = user;
}
}
2.2 工厂 (Factory)
UserFactory.java
typescript
public class UserFactory {
public static User createUser(Long id, String name) {
User user = new User();
user.setId(id);
user.setName(name);
// 其他属性设置
return user;
}
}
2.3 领域服务 (Domain Service)
RoleAssignmentService.java
typescript
public class RoleAssignmentService {
public void assignRoleToUser(User user, Role role) {
if (user.hasRole(role)) {
throw new DomainException("User already has the role");
}
user.addRole(role);
}
}
2.4 领域事件 (Domain Event)
UserCreatedEvent.java
scala
public class UserCreatedEvent extends Event {
private User user;
public UserCreatedEvent(User user) {
this.user = user;
}
public User getUser() {
return user;
}
}
2.5 领域异常 (Domain Exception)
DomainException.java
scala
public class DomainException extends RuntimeException {
public DomainException(String message) {
super(message);
}
}
3. 应用层 (ddd-application)
3.1 应用服务 (Application Service)
UserService.java
java
public interface UserService {
void createUser(UserDTO userDTO);
void updateUser(UserDTO userDTO);
void deleteUser(Long id);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserMapper userMapper;
@Autowired
private EventPublisher eventPublisher;
public void createUser(UserDTO userDTO) {
User user = userMapper.toEntity(userDTO);
userRepository.save(user);
eventPublisher.publish(new UserCreatedEvent(user));
}
public void updateUser(UserDTO userDTO) {
User user = userRepository.findById(userDTO.getId());
if (user == null) {
throw new RuntimeException("User not found");
}
user.setName(userDTO.getName());
// 其他属性更新
userRepository.save(user);
}
public void deleteUser(Long id) {
User user = userRepository.findById(id);
if (user == null) {
throw new RuntimeException("User not found");
}
userRepository.delete(user);
}
}
RoleService.java
java
public interface RoleService {
void createRole(RoleDTO roleDTO);
void updateRole(RoleDTO roleDTO);
void deleteRole(Long id);
}
@Service
public class RoleServiceImpl implements RoleService {
@Autowired
private RoleRepository roleRepository;
@Autowired
private RoleMapper roleMapper;
public void createRole(RoleDTO roleDTO) {
Role role = roleMapper.toEntity(roleDTO);
roleRepository.save(role);
}
public void updateRole(RoleDTO roleDTO) {
Role role = roleRepository.findById(roleDTO.getId());
if (role == null) {
throw new RuntimeException("Role not found");
}
role.setName(roleDTO.getName());
// 其他属性更新
roleRepository.save(role);
}
public void deleteRole(Long id) {
Role role = roleRepository.findById(id);
if (role == null) {
throw new RuntimeException("Role not found");
}
roleRepository.delete(role);
}
}
3.2 数据传输对象 (DTO)
UserDTO.java
kotlin
public class UserDTO {
private Long id;
private String name;
// 其他属性
// getter、setter 省略
}
RoleDTO.java
kotlin
public class RoleDTO {
private Long id;
private String name;
// 其他属性
// getter、setter 省略
}
4. 表示层 (ddd-interface)
4.1 控制器 (Controller)
UserController.java
less
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private UserMapper userMapper;
@PostMapping
public void createUser(@RequestBody UserDTO userDTO) {
userService.createUser(userDTO);
}
@PutMapping
public void updateUser(@RequestBody UserDTO userDTO) {
userService.updateUser(userDTO);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
}
4.2 值对象 (VO)
UserVO.java
kotlin
public class UserVO {
private Long id;
private String name;
// 其他属性
// getter、setter 省略
}
RoleVO.java
kotlin
public class RoleVO {
private Long id;
private String name;
// 其他属性
// getter、setter 省略
}
三、补充内容
1. 聚合与聚合根
在领域驱动设计中,聚合是业务一致性边界,聚合根是聚合的根实体,负责维护聚合内部的一致性。
在这个系统中,User
是聚合根,Role
是聚合中的实体。User
负责维护与 Role
之间的关系。
User.java
typescript
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Set<Role> roles = new HashSet<>();
// 构造器、getter、setter 省略
public void addRole(Role role) {
roles.add(role);
role.setUser(this);
}
public void removeRole(Role role) {
roles.remove(role);
role.setUser(null);
}
}
2. 防腐层 (Anti-Corruption Layer)
防腐层用于隔离外部系统对领域层的影响,通常使用适配器模式来实现。
在这个系统中,假设我们使用的是JPA作为数据访问技术,可以在基础设施层添加一个防腐层,将JPA的具体实现隔离在防腐层中。
UserDAO.java
csharp
public interface UserDAO {
void save(User user);
User findById(Long id);
void delete(User user);
}
UserDAOJPAAdapter.java
typescript
@Repository
public class UserDAOJPAAdapter implements UserDAO {
@PersistenceContext
private EntityManager entityManager;
public void save(User user) {
entityManager.persist(user);
}
public User findById(Long id) {
return entityManager.find(User.class, id);
}
public void delete(User user) {
entityManager.remove(user);
}
}
我是栈江湖,如果你喜欢此文章,不要忘记点赞+关注!