Java8/Spring5项目:服务定位器模式下可配置Validator子集实现方案
我来分享一个适配Java 8/Spring 5环境、严格遵循SOLID原则且完全配置化的最优实现方案,完美匹配你的需求:
核心思路概述
通过Spring原生特性+配置映射+抽象封装的组合,实现IBase实现类与Validator子集的动态绑定,全程无需硬编码逻辑,同时满足开闭、单一职责等SOLID要求。
1. 配置层:定义IBase与Validator的映射规则
在application.properties中添加配置,直接指定每个IBase实现类(全限定名)对应的Validator Bean名称列表:
# 格式:base.validators.[IBase实现类全限定名]=[逗号分隔的Validator Bean名称] base.validators.com.example.service.IBaseImplA=validatorA base.validators.com.example.service.IBaseImplB=validatorB,validatorC base.validators.com.example.service.IBaseImplC=validatorA,validatorB,validatorC,validatorN # 单独控制每个Validator是否启用(对应原需求的enabled属性) validators.validatorA.enabled=true validators.validatorB.enabled=true validators.validatorC.enabled=true validators.validatorN.enabled=true
2. Validator层:基于Spring条件注解动态加载
用Spring的@ConditionalOnProperty替代手动init方法判断,让Spring自动管理Validator Bean的创建与否,完全符合Spring生态:
@Component("validatorA") @ConditionalOnProperty(prefix = "validators", name = "validatorA.enabled", havingValue = "true", matchIfMissing = true) public class ValidatorA implements Validator { @Override public void validate(Request req) { // 具体验证逻辑 } }
- 当
enabled为true时,该Validator会被注册为Spring Bean;反之则不会被加载 matchIfMissing = true配置可以让Validator默认启用,无需额外配置
3. 映射器层:实现IBase与Validator的动态绑定
创建一个单一职责的ValidatorMapper组件,负责读取配置、建立映射关系,同时提供根据IBase实例获取对应Validator列表的方法:
@Component public class ValidatorMapper { private final Map<String, List<Validator>> validatorMap = new ConcurrentHashMap<>(); private final ApplicationContext applicationContext; // 构造注入Spring上下文与配置映射 public ValidatorMapper(ApplicationContext applicationContext, @Value("#{${base.validators}}") Map<String, String> baseValidatorConfig) { this.applicationContext = applicationContext; initValidatorMapping(baseValidatorConfig); } // 初始化映射关系 private void initValidatorMapping(Map<String, String> config) { config.forEach((baseClassFullName, validatorNames) -> { List<Validator> validators = Arrays.stream(validatorNames.split(",")) .map(String::trim) .map(applicationContext::getBean) .map(Validator.class::cast) .collect(Collectors.toList()); validatorMap.put(baseClassFullName, validators); }); } // 根据IBase实例获取对应的Validator子集 public List<Validator> getValidatorsForBase(IBase baseInstance) { String className = baseInstance.getClass().getName(); return validatorMap.getOrDefault(className, Collections.emptyList()); } }
- 完全配置化:新增IBase实现或Validator,仅需修改配置文件,无需修改代码
- 容错处理:可以在
initValidatorMapping中添加日志或异常捕获,处理配置的Validator Bean不存在的情况
4. IBase层:抽象封装验证逻辑,避免重复代码
创建抽象基类AbstractBase,封装验证逻辑,让所有IBase实现类专注于业务逻辑,符合单一职责原则:
public abstract class AbstractBase implements IBase { @Autowired private ValidatorMapper validatorMapper; // 统一验证入口 protected void validateRequest(Request req) { List<Validator> validators = validatorMapper.getValidatorsForBase(this); validators.forEach(validator -> validator.validate(req)); } // 模板方法:先验证再执行业务 @Override public void handleRequest(Request req) { validateRequest(req); executeBusinessLogic(req); } // 子类实现具体业务逻辑 protected abstract void executeBusinessLogic(Request req); }
然后让所有IBase实现类继承该抽象类:
@Component("baseA") public class IBaseImplA extends AbstractBase { @Override protected void executeBusinessLogic(Request req) { // IBaseImplA的具体业务逻辑 } }
5. 适配Service Locator Pattern
由于你的IBase实现基于Service Locator运行,只需用Spring的ServiceLocatorFactoryBean实现Locator接口,确保获取到的IBase实例已自动注入ValidatorMapper:
@Configuration public class ServiceLocatorConfig { @Bean public ServiceLocatorFactoryBean baseServiceLocator() { ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean(); factoryBean.setServiceLocatorInterface(IBaseLocator.class); return factoryBean; } // 定义Service Locator接口 public interface IBaseLocator { IBase getBase(String baseBeanName); // 根据Bean名称获取IBase实例 } }
为什么符合SOLID原则?
- 单一职责:Validator只做验证、ValidatorMapper只做映射、IBase实现只做业务逻辑
- 开闭原则:新增IBase实现或Validator,仅需添加配置和对应类,无需修改现有代码
- 里氏替换:所有IBase子类可无缝替换抽象基类,不影响功能
- 接口隔离:Validator接口仅包含
validate方法,IBase接口专注于业务方法,无冗余依赖 - 依赖倒置:IBase实现依赖抽象的Validator接口和ValidatorMapper服务,而非具体实现类
内容的提问来源于stack exchange,提问作者Valamorde
相关产品推荐
相关产品推荐

