如何简化Java应用中泛型接口多实现的依赖注入?
优雅管理多个泛型验证器的方案
给你两个实用的方案,不用再逐个声明不同类型的InputsValidator:
方案一:用Spring自动注入Map集合
Spring会自动把所有实现InputsValidator接口的Bean注入到一个Map里,key是Bean的默认名称(首字母小写的类名),value对应具体的验证器实例。你可以封装一个工具方法,根据输入类型获取对应的验证器。
代码示例:
@Component @RequiredArgsConstructor class MyServiceApiImpl extends DelegateHelper implements UserApiDelegate { // Spring自动注入所有InputsValidator实现类 private final Map<String, InputsValidator<?>> validatorMap; // 根据输入类型获取对应验证器的工具方法 @SuppressWarnings("unchecked") private <T> InputsValidator<T> getValidator(Class<T> inputType) { // 拼接Bean名称:比如Address类对应addressInputsValidator String beanName = inputType.getSimpleName().substring(0, 1).toLowerCase() + inputType.getSimpleName().substring(1) + "InputsValidator"; return (InputsValidator<T>) validatorMap.get(beanName); } // 使用示例:验证Address public void handleAddress(Address address) { InputsValidator<Address> validator = getValidator(Address.class); List<MessageEnum> messages = validator.validator(address); // 后续处理验证结果 } // 使用示例:验证Contact public void handleContact(Contact contact) { InputsValidator<Contact> validator = getValidator(Contact.class); List<MessageEnum> messages = validator.validator(contact); // 后续处理验证结果 } }
方案二:自定义验证器工厂类
写一个工厂类统一管理所有验证器,启动时通过反射识别每个验证器对应的泛型输入类型,把类型和验证器实例做映射。之后在业务类里只需要注入这个工厂,就能根据类型获取验证器。
第一步:写工厂类
@Component public class InputsValidatorFactory { private final Map<Class<?>, InputsValidator<?>> validatorMap = new HashMap<>(); // 构造方法注入所有InputsValidator实现类,初始化映射关系 public InputsValidatorFactory(List<InputsValidator<?>> validators) { for (InputsValidator<?> validator : validators) { // 反射获取泛型接口的实际参数类型 Type genericInterface = validator.getClass().getGenericInterfaces()[0]; if (genericInterface instanceof ParameterizedType) { ParameterizedType paramType = (ParameterizedType) genericInterface; Class<?> inputClass = (Class<?>) paramType.getActualTypeArguments()[0]; validatorMap.put(inputClass, validator); } } } // 根据输入类型获取验证器 @SuppressWarnings("unchecked") public <T> InputsValidator<T> getValidator(Class<T> inputType) { return (InputsValidator<T>) validatorMap.get(inputType); } }
第二步:在业务类中使用工厂
@Component @RequiredArgsConstructor class MyServiceApiImpl extends DelegateHelper implements UserApiDelegate { private final InputsValidatorFactory validatorFactory; // 验证Address示例 public void handleAddress(Address address) { InputsValidator<Address> validator = validatorFactory.getValidator(Address.class); List<MessageEnum> messages = validator.validator(address); // 处理验证结果 } }
方案对比
- 方案一简单直接,不需要额外写工厂,但要保证Bean名称和类名的拼接规则一致;如果自定义了Bean名称,得调整拼接逻辑。
- 方案二更灵活,不用依赖Bean名称,自动识别泛型类型,适合验证器数量多或者Bean名称不固定的场景,反射只在启动时执行一次,性能几乎不受影响。
内容的提问来源于stack exchange,提问作者Youcef LAIDANI
相关产品推荐
相关产品推荐

