service层代码相互调用, 导致spring循环依赖, 我这样设计是不是还不错, 有更好的做法吗?

我觉得软件设计方面比较难的一点就是, 什么方法该放到什么类中才合适, 不至于越来越混乱, 有个比较常见的需求就是

管理员创建用户需要发送激活邮件, 而发送激活邮件的时候需要判断发件人是不是合法的用户, 因此设计到一个循环依赖的问题

这个问题可能稍微有点不恰当, 过滤器就可以实现, 先不考虑这些因素

UserService 依赖 MailService, 而 MailService 又依赖 UserService

代码如下:

//UserService
@Service
class UserService{
    @Autowired
    private MailService mailService;
    
    @Autowired
    private UserMapper userMapper;
    
    public void createUser(User user){
        //创建用户
        userMapper.save(user);
        
        //发送邮件
        mailService.send(xxxx);
    }
    
    //判断用户是否合法
    public boolean isExist(String userId){//.... userMapper.xxxx}
}

//MailService
@Service
class MailService{
    @Autowired
    private UserService userService;
    
    @Autowired
    private UserMapper userMapper;
    public void send(Mail mail){
        //判断发件人是否存在
        String currentUserId = SessionContext.getCurrentUser().getUserId();
        if(!userService.isExist(currentUserId)){
            //用户不存在抛异常
        }
            //send mail
    }
}

这样的代码spring启动的时候就监测到循环依赖而启动失败, 那么再增加一个Service吧, 用于存放辅助方法, 将
isExist都移动到这类方法中

//UserServiceHelper
@Service
class UserServiceHelper{
    @Autowired
    private UserMapper userMapper;
    
    //判断用户是否合法
    public boolean isExist(String userId){//.... userMapper.xxxx}
    
}

那么MailService就变成了

@Service
class MailService{
    
    @Autowired
    private UserServiceHelper userServiceHelper; //这里不同了
    
    public void send(Mail mail){
        //判断发件人是否存在
        String currentUserId = SessionContext.getCurrentUser().getUserId();
        if(!userServiceHelper.isExist(currentUserId)){
            //用户不存在抛异常
        }
            //send mail
    }
}

有人会说注入 UserMapper 不就行了, 是可以但是每次都调用Mapper的方法较为麻烦, 即使只多一行代码, 但是这种代码是没有语义化的, 不能一眼看出来是判断用户是否存在的

这个方法比较简单, 不知道还有没有更高级的做法呢?????????????????

阅读 14.8k
1 个回答

发送邮件和判断用户是否存在是两个独立的部分,不应该紧耦合在一起,你应该是在调用处组合二者的逻辑:

UserService {
  // CRUD
  boolean isExists(String userId);
}

MailService {
  void send(Mail mail);
}

UserExistsCheckMailService {
  UserService userService;
  MailService mailService;
  void send(Mail mail) {
    if (!userService.isExists(...)) {
      throw Exception;
    }
    mailService.send()
  }
}

关于如何组织代码,你应该去找SOLID原则的相关资料看,然后找设计模式的相关资料。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题