我有一个 Java Spring-boot 应用程序,它有图层(包):
在我的Domain
里面我有两个数据库类
我的service package
中有很多课程,它们使用MysqlDBManager
和MongoDBManager
的方法。
我直接在我的服务类上使用MysqlDBManager' and
MongoDBManager`的实例,然后 service 图层将紧密与域图层耦合。
为了解决这个问题,我在域包中创建了一个名为**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);
}
我的问题是:
这是(如上所述)使我的应用程序层松散耦合的好方法,或者它们存在更好的方法吗?
答案 0 :(得分:4)
恕我直言,有一种更好的方法,接口可以帮助你松散地耦合图层,这是一个例子:
interface DocsDBManager {
void saveUserDocs(String docs);
}
interface UserDBManager {
void saveUserData(List<String> rows);
}
interface DBManager extends DocsDBManager, UserDBManager {
}
你必须实施它们:
class MongoDBManager implements DocsDBManager {
public void saveUserDocs(String docs) {
//.....
}
}
class MysqlDBManager implements UserDBManager {
public void saveUserData(List<String> rows) {
//.....
}
}
和
class DBManagerBase implements DBManager {
@Autowired
private DocsDBManager docsDBManager;
@Autowired
private UserDBManager userDBManager;
public void saveUserData(List<String> rows) {
userDBManager.saveUserData(rows);
}
public void saveUserDocs(String docs) {
docsDBManager.saveUserDocs(docs);
}
}
最后:
class Service {
@Autowired
private DBManager dBManager;
//....... code here
dBManager.saveUserData(rows);
dBManager.saveUserDocs(docs);
}
答案 1 :(得分:4)
你的方法很好,它看起来像某种Facade设计模式,但我会推荐更传统的方式。
你已经有了spring作为IoC容器,所以你要做的就是从你的*DBManager
类中提取接口,然后告诉你实现的内容。然后,您将能够使用接口注入实际实现,而接口又可能位于完全不同的包中。因此,耦合将不复存在。
这是一个例子。
DataStorage合同:
package root;
import java.util.List;
public interface UserDataStorage {
void saveUserData(List<String> rows);
}
DocumentStorage合同:
package root;
public interface UserDocumentStorage {
void saveUserDocs(String docs);
}
DataStorage实施:
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");
}
}