
本文介绍一种通过依赖注入简化服务类获取专属配置的模式,避免在每个服务中重复调用 `configuration.getxxx()`,提升代码内聚性与可测试性。
在典型的分层配置架构中,Configuration 作为顶层聚合对象,封装多个子配置(如 ConfA、ConfB),而各服务(ServiceA、ServiceB)仅需其中一部分。若强制所有服务接收完整 Configuration 对象,不仅违背单一职责原则,还会导致冗余访问逻辑和隐式耦合。
推荐方案:面向配置契约的接口级依赖注入
核心思想是——让每个服务直接声明其真正需要的配置类型,而非整个 Configuration。这可通过重构 Service 接口实现:
// 原始泛化接口(不推荐)
public interface Service {
void work(Configuration configuration);
}应升级为泛型化或专用化接口,例如:
// 方案一:泛型接口(更灵活,支持统一调度) public interface Service{ void work(T config); } public class ServiceA implements Service { @Override public void work(ConfA confA) { // 直接使用 confA,零胶水代码 System.out.println("Using A config: " + confA.getHost()); } } public class ServiceB implements Service { @Override public void work(ConfB confB) { System.out.println("Using B config: " + confB.getTimeout()); } }
或采用更清晰的专用接口(语义更强,利于 IDE 提示与编译检查):
public interface ServiceA {
void execute(ConfA config);
}
public interface ServiceB {
void execute(ConfB config);
}配套的启动/协调层负责装配:
public class ConfigurationLoader {
private final Configuration configuration;
public ConfigurationLoader(Configuration configuration) {
this.configuration = configuration;
}
public void runAllServices() {
new ServiceA().execute(configuration.getConfA());
new ServiceB().execute(configuration.getConfB());
// 或通过 Spring 等容器自动注入:@Autowired private ServiceA serviceA;
}
}✅ 优势总结:
- 消除重复提取逻辑:每个服务不再关心“如何从大配置中找自己那部分”;
- 增强类型安全:编译期即校验配置契约,避免运行时 NullPointerException;
- 提升可测性:单元测试可直接传入模拟配置对象,无需构造完整 Configuration;
- 符合依赖倒置原则(DIP):服务依赖具体配置契约,而非高层聚合对象。
⚠️ 注意事项:
- 若存在跨服务共享配置字段的场景,建议抽取公共配置基类(如 BaseConf),再由 ConfA/ConfB 继承,保持复用性;
- 在 Spring 等框架中,可结合 @ConfigurationProperties 与 @Bean 方法实现自动绑定与注入,进一步减少样板代码;
- 避免为图方便将 Configuration 强转或反射获取子配置——这会破坏封装性与可维护性。
该模式本质是将“配置解析责任”上移至装配层,使业务服务回归纯粹逻辑表达,是构建高内聚、低耦合配置驱动系统的关键实践。










