我有一个 Java Spring引导应用程序,该应用程序具有图层():

  • 控制器(控制器类)
  • 服务(业务逻辑)
  • 域(数据库层)

  • 在我的Domain内部,我有两个数据库类
  • MysqlDBManager
  • MongoDBManager

  • 我的service package中有很多类,它们同时使用MysqlDBManagerMongoDBManager的方法。

    如果 我直接在我的服务类上使用MysqlDBManager' and MongoDBManager`的实例,则服务层将层紧密耦合。

    为了解决这个问题,我在包中创建了一个名为**DBManager**的类,该类充当代理类,该代理类根据内部用例调用MysqlDBManager' and MongoDBManager`。

    现在服务层,而不是调用MysqlDBManager' and MongoDBManager directly they call DBManager , which internally calls MysqlDBManager'和MongoDBManager

    因此,现在我的服务类别与领域层并没有紧密联系。

    以下是与用例相似的类。

    MongoDBManager类:
     Class  MongoDBManager {
           public saveUserDocs(String docs) {
             //.....
           }
        }
    

    MysqlDBManager类:
    Class  MysqlDBManager {
           public saveUserData(List<String> rows) {
             //.....
           }
        }
    

    DBManager类:
     Class  DBManager {
    
               @Autowired
               private MysqlDBManager mysqlDBManager;
               @Autowired
               private MongoDBManager mongoDBManager;
    
               public saveUserData(List<String> rows) {
                 mysqlDBManager.saveUserData(rows);
               }
    
               public saveUserDocs(String docs) {
                 mongoDBManager.saveUserDocs(docs);
               }
            }
    

    服务类别:
    class Service {
        @Autowired
        private DBManager dBManager;
    
        //....... code here
        dBManager.saveUserData(rows);
        dBManager.saveUserDocs(docs);
    }
    

    我的问题是:

    这(如上所述)是使我的应用程序层松散耦合的好方法,还是存在更好的方法呢?

    最佳答案

    您的方法很好,它看起来像某种Facade设计模式,但我建议您使用更传统的方法。

    您已经拥有spring作为IoC容器,因此您所要做的就是从*DBManager -classes中提取接口,并告诉spring您的实现。然后,您将能够使用接口注入实际的实现,而该接口又可能位于完全不同的包中。因此,耦合将不复存在。

    这是一个例子。

    数据存储合同:

    package root;
    
    import java.util.List;
    
    public interface UserDataStorage {
        void saveUserData(List<String> rows);
    }
    

    文档存储合同:
    package root;
    
    public interface UserDocumentStorage {
        void saveUserDocs(String docs);
    }
    

    数据存储实现:
    package root.domain;
    
    import org.springframework.stereotype.Service;
    import root.UserDataStorage;
    
    import java.util.List;
    
    @Service
    public class MysqlDBManager implements UserDataStorage {
        @Override
        public void saveUserData(List<String> rows) {
            System.out.println("Saving data....");
        }
    }
    

    DocumentStorage实现:
    package root.domain;
    
    import org.springframework.stereotype.Service;
    import root.UserDocumentStorage;
    
    @Service
    public class MongoDBManager implements UserDocumentStorage {
        @Override
        public void saveUserDocs(String docs) {
            System.out.println("Saving docs....");
        }
    }
    

    然后您的服务类可能如下所示(请注意,没有对domain包的引用:
    package root.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import root.UserDataStorage;
    import root.UserDocumentStorage;
    
    import java.util.Collections;
    
    @Service
    public class MyService {
    
        private final UserDataStorage dataStorage;
        private final UserDocumentStorage documentStorage;
    
        @Autowired
        public MyService(UserDataStorage dataStorage, UserDocumentStorage documentStorage) {
            this.dataStorage = dataStorage;
            this.documentStorage = documentStorage;
        }
    
        public void callMe() {
            this.dataStorage.saveUserData(Collections.emptyList());
            this.documentStorage.saveUserDocs("Document1");
        }
    }
    

    07-26 09:03