我已经看到一些关于在类中包装一组配置属性的问题,而不是如何实际使用它.给定一个配置类(为简洁省略getter和setter): class ServiceConfiguration { private String foo; } 服务类应该直接使用配置
class ServiceConfiguration { private String foo; }
服务类应该直接使用配置吗?
static class SomeServiceB { private ServiceConfiguration configuration; public SomeServiceB(ServiceConfiguration configuration) { this.configuration = configuration; } public void printIt() { System.out.println(configuration.getFoo()); } }
或者它应该只关注foo的实际价值?例如:
static class SomeServiceA { private String foo; public SomeServiceA(String foo) { this.foo = foo; } public void printIt() { System.out.println(foo); } }
我认为SomeServiceA是优越的,因为较低的耦合和关注点分离.
两种方案都是正确的.重要的是,类只依赖于它实际使用的配置值.这意味着注入一个包含所有配置值的ApplicationConfiguration对象,或允许访问所有应用程序配置值是一个坏主意,因为这使得不清楚该类实际使用的配置值并推迟配置值的读取可能导致配置错误只是很晚才出现.口头禅是:快速失败.
注入一个封装类所需值的对象通常比在单独的构造函数参数中注入所有这些值更方便.这基本上是Parameter Object refactoring.
将配置值(即使只是一个)包装到参数对象中的另一个好处是,它允许DI容器自动连接此类.当类具有除配置值之外的依赖项时,这尤其有用.例如:
class SomeServiceB { public SomeServiceB(IDep1 d1, IDep2 d2, SomeServiceConfig config) { } }
DI容器不能轻易地自动连接原始值,因为字符串和整数等值是不明确的:您可能有多个具有不同含义的值的实例.例如,您可能同时拥有连接字符串和文件路径.两者都是字符串.
尽管使配置对象不可变,但要清楚地表明它们无法更改是很重要的.您通常应该在应用程序启动时构造它们并将它们注册为单例.