首页 > 解决方案 > 在 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);
    }
}

好的,那么问题是什么?当我注入类型的beanUserDaoUserService其他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();
    }
}

接口ConversationServiceUserDao具有泛型类型,因此会出现警告:

在此处输入图像描述 在此处输入图像描述

我不想放弃泛型类型,但另一方面我知道注入没有泛型类型会导致不符合干净代码原则的警告。确实,尽管有警告,但这种设计仍然有效。当我将持久层从 MongoDb 更改为 JPA 时,我不想更改的实现EntryPoint,我只想为域接口(,等)提供UserUserDaoUserService实现

如何协调域域类的接口问题和没有泛型类型的注入?

标签: javaspringspring-data

解决方案


推荐阅读