java - 在 Spring 中使用域类和通用服务的接口
问题描述
我想要实现的是使用域类的接口和服务层的泛型类型,并且能够将持久层的实现从当前的 MongoDb 更改为例如 JPA。域类的接口是必要的,因为例如 JPA 和 MongoDB (@Entity
和@Document
) 的注释不同。
让我们看一下以下演示项目的结构:
对于领域模型的每个元素,可以有三个接口,我们用user
包来解释一下:
User
- 领域对象的表示
UserDao
- 提供持久层方法
UserService
- 提供业务逻辑方法
以下是它们每个的接口:
public interface User {
String getId();
String getFirstName();
String getLastName();
List<Consent> getConsents();
Boolean getBlocked();
}
public interface UserDao <UserType extends User> {
UserType save(UserType user);
Optional<UserType> getById(String userId);
}
public interface UserService <UserType extends User> {
UserType create(String firstName, String lastName);
void addConsent(UserType user, ConsentType consentType);
}
正如我之前提到的,这些接口的当前实现与 Mongo DB 有关:
@Getter
@Setter
@Document(collection = "user")
public class MongoUser extends AbstractMongoCollection implements User {
private String firstName;
private String lastName;
private List<PojoConsent> consents;
private Boolean blocked;
void addConsent(PojoConsent consent) {
if(consents == null) {
consents = new ArrayList<>();
}
consents.add(consent);
}
@Override
public List<Consent> getConsents() {
return new ArrayList<>(consents);
}
}
@Component
public class MongoUserDao implements UserDao<MongoUser> {
private MongoUserRepository mongoUserRepository;
@Autowired
public MongoUserDao(MongoUserRepository mongoUserRepository) {
this.mongoUserRepository = mongoUserRepository;
}
@Override
public MongoUser save(MongoUser user) {
return mongoUserRepository.save(user);
}
@Override
public Optional<MongoUser> getById(String userId) {
return mongoUserRepository.findByIdAndDeletedIsFalse(userId);
}
}
@Component
public class MongoUserService implements UserService<MongoUser> {
private UserDao<MongoUser> userDao;
@Autowired
public MongoUserService(UserDao<MongoUser> userDao) {
this.userDao = userDao;
}
@Override
public MongoUser create(String firstName, String lastName) {
MongoUser user = new MongoUser();
user.setBlocked(false);
user.setFirstName(firstName);
user.setLastName(lastName);
user.setDeleted(false);
return userDao.save(user);
}
@Override
public void addConsent(MongoUser user, ConsentType consentType) {
PojoConsent pojoConsent = new PojoConsent();
pojoConsent.setActive(true);
pojoConsent.setType(consentType);
pojoConsent.setDate(LocalDateTime.now());
user.addConsent(pojoConsent);
userDao.save(user);
}
}
好的,那么问题是什么?当我注入类型的beanUserDao
和UserService
其他bean时会出现问题(就像在Spring Framework中发生的那样),就像EntryPoint
在这个例子中一样(我知道spring控制器中不应该有逻辑,但这只是一个例子):
@RestController
@RequestMapping("/api")
public class EntryPoint {
@Autowired
private ConversationService conversationService;
@Autowired
private UserDao userDao;
@PostMapping("/create/{userId}")
public ResponseEntity<String> createConversation(@PathVariable("userId") String userId) {
Optional<User> optionalUser = userDao.getById(userId);
if(optionalUser.isPresent()) {
User user = optionalUser.get();
Conversation conversation = conversationService.create(user, "default");
return ResponseEntity.ok(conversation.getId());
}
return ResponseEntity.notFound().build();
}
}
接口ConversationService
并UserDao
具有泛型类型,因此会出现警告:
我不想放弃泛型类型,但另一方面我知道注入没有泛型类型会导致不符合干净代码原则的警告。确实,尽管有警告,但这种设计仍然有效。当我将持久层从 MongoDb 更改为 JPA 时,我不想更改的实现EntryPoint
,我只想为域接口(,等)提供User
新UserDao
的UserService
实现
如何协调域域类的接口问题和没有泛型类型的注入?
解决方案
推荐阅读
- java - 使用 PeriodicRotatingFileHandler 写入文件
- git - 检索 TFS 集合和项目的列表
- html - HTML 元素的嵌套顺序如何影响 CSS 特异性?
- swift - MKPolyline 的标注
- python - 如何实现只执行“K”次的冒泡排序
- hive - 如何在配置单元表中将 UAD 汇率更改为 CAD 汇率
- android - Glide 无法正确旋转来自相机的图像
- tensorflow - 试图了解如何使用 for 循环将更多隐藏层添加到神经网络中
- jquery - 为什么我的每个循环都以相反的顺序打印
- laravel - 用户通过身份验证时如何在 API 响应中包含额外数据