
本文介绍一种基于依赖注入的简洁模式,避免在每个服务中重复调用 configuration.getxxx() 获取子配置,让服务直接接收其所需的特定配置实例,提升内聚性与可测试性。
在典型的分层配置架构中,Configuration 作为顶层聚合对象封装多个子配置(如 ConfA、ConfB),而不同服务(ServiceA、ServiceB)仅需其中一部分。若坚持让所有服务统一接收完整 Configuration 对象,就会导致每个实现类都需手动提取对应子配置——不仅冗余,还造成服务与顶层配置结构强耦合,违反单一职责原则。
更优解是面向契约设计 + 构造器/方法级依赖注入:将服务接口的抽象粒度下沉至具体配置类型,使服务只声明它真正需要的依赖。
✅ 推荐重构方式如下:
-
细化服务接口定义(按配置类型划分):
public interface Service
{ void work(T config); }
// 具体实现直接绑定所需配置类型
public class ServiceA implements Service
public class ServiceB implements Service
2. **启动/编排层负责依赖装配**(例如 Spring 或手动工厂):
```java
@Configuration
public class AppConfig {
@Bean
public ServiceA serviceA(ConfA confA) {
return new ServiceA();
}
@Bean
public ServiceB serviceB(ConfB confB) {
return new ServiceB();
}
// Configuration bean 可保留用于初始化或调试,但不再直接注入到业务服务
@Bean
public Configuration configuration() {
return new Configuration(confA(), confB());
}
}⚠️ 注意事项:
- 若必须维持统一 Service 接口(如框架强制要求),可引入适配器模式:ServiceBAdapter 包装 ServiceB,在 work(Configuration) 中自动提取 confB 并委托调用,将胶水逻辑集中化;
- 避免在服务内部反向持有 Configuration 引用——这会隐式引入不必要的依赖和潜在的配置访问错误;
- 配置类建议设为不可变(final 字段 + 构造器注入),配合 @ConfigurationProperties(Spring Boot)等机制保障线程安全与验证能力。
总结:服务不应承担“找配置”的责任,而应由容器或装配层确保其获得恰好的配置实例。 这一转变不仅消除了重复代码,更推动系统向关注点分离、低耦合、高可测的方向演进。










