Я хочу создать обобщенную пружину только один раз для всех случаев, чтобы избежать дублирования кода. Рассмотрим пример, в котором мне нужен один валидатор для событий входа и покупки.
События
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' , не помогут.