Работа с интерфейсами для классов доменов и сервисов generi c в Spring - PullRequest
0 голосов
/ 19 марта 2020

Чего я хотел бы добиться, так это использовать интерфейсы для классов доменов и обобщенные типы c для уровня обслуживания и иметь возможность изменить реализацию уровня постоянства с текущего, который является MongoDb, например, на JPA. Интерфейсы для классов домена необходимы, например, из-за различных аннотаций для JPA и MongoDB (@Entity и @Document).

Давайте рассмотрим структуру следующего демонстрационного проекта:

enter image description here

Для каждого элемента модели предметной области может быть три интерфейса, объясним это с помощью пакета user:

User - представление объекта предметной области

UserDao - предоставление методов постоянного уровня

UserService - предоставление бизнес-логики c методов

Вот интерфейсы для каждого из них:

    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);
    }

Как я упоминал ранее, текущая реализация этих интерфейсов связана с Mon go 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);
    }
}

Хорошо, так что же проблема? Проблема возникает, когда я внедряю bean-компоненты типа UserDao и UserService в другие bean-компоненты (как это происходит в Spring Framework), например EntryPoint в этом примере (я знаю, что логики c не должно быть) в контроллере пружины, но это только пример):

@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 имеют тип generi c, поэтому появляются предупреждения:

enter image description here enter image description here

Я не хочу отказываться от универсальных c типов, но, с другой стороны, я знаю, что инъекции без универсальных c типов будет вызывать предупреждения, которые не соответствуют принципам чистого кода. Это правда, что этот дизайн будет работать, несмотря на предупреждения. Я не хочу менять реализацию EntryPoint, когда я изменяю уровень персистентности с MongoDb на JPA, я просто хочу предоставить новую реализацию для доменных интерфейсов (User, UserDao, UserService et c. )

Как решить проблему с интерфейсом для классов доменов домена и инъекций без универсального c типа?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...