Как обрешетить обобщенную пружину всего один раз на все случаи - PullRequest
1 голос
/ 05 мая 2020

Я хочу создать обобщенную пружину только один раз для всех случаев, чтобы избежать дублирования кода. Рассмотрим пример, в котором мне нужен один валидатор для событий входа и покупки.

События

interface UserEvent {
    int getUserId();
}

@Value
class LoginEvent implements UserEvent {
    int userId;
    long timestamp;
}

@Value
class PurchaseEvent implements UserEvent {
    int userId;
    long transactionId;
}

Валидатор, который определяет, является ли пользователь из события действительным

class UserValidator<T extends UserEvent> {

    public T isUserValid(T event) {
        if (event.getUserId() % 3 == 0) {
            return event;
        }
        throw new RuntimeException(String.format("User with id=%d is invalid", event.getUserId()));
    }
}

Контекст с валидаторами

@Configuration
class ValidatorContext {

    @Bean
    public UserValidator<LoginEvent> userValidatorOnLogin() {
        return new UserValidator<>();
    }

    @Bean
    public UserValidator<PurchaseEvent> userValidatorOnPurchase() {
        return new UserValidator<>();
    }
}

Контекст службы

@Configuration
class ServiceContext {

    @Bean
    public LoginService loginService(UserValidator<LoginEvent> userValidatorOnLogin) {
        return new LoginService(loginValidator);
    }

    @Bean
    public PurchaseService purchaseService(UserValidator<PurchaseEvent> userValidatorOnPurchase) {
        return new PurchaseService(purchaseValidator);
    }
}

Проблема, которую я заставил создать валидаторы для обоих типов событий. Можно ли создать валидатор только один раз, как здесь?

@Configuration
class Context {

    @Bean
    public UserValidator<UserEvent> userValidator() {
        return new UserValidator<>();
    }
}

И внедрить его в службы

@Configuration
class ServiceContext {

    @Bean
    public LoginService loginService(UserValidator<LoginEvent> userValidator) {
        return new LoginService(loginValidator);
    }

    @Bean
    public PurchaseService purchaseService(UserValidator<PurchaseEvent> userValidator) {
        return new PurchaseService(purchaseValidator);
    }
}

Если вы обратили внимание, валидатор возвращает исходный объект со спецификой c тип. Это потому, что в бизнес-потоке (LoginService PurchaseService) мне нужен этот конкретный тип c. И это главная проблема. К тому же реальный случай намного сложнее, и этот пример максимально упрощен для понимания проблемы. Таким образом, любой рефакторинг или подсказки, такие как ', используют исходный объект, который вы используете в качестве параметра для isUserValid в вашем бизнес-логе c' , не помогут.

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