java - 使静态变量可注入(inject)

标签 java dependency-injection

我正在构建一个 http API 客户端,需要调用特定端点,如下所示:

public class MyApiClient {
    private static final String ENDPOINT ="http://myapi....";

}

这里端点不会改变,因此它是常量。但是,我希望能够覆盖它以进行测试,以便我可以针对模拟 http 服务器进行测试。

最好的方法是什么?难道只是让它成为一个实例变量并为其提供一个起始值:

private String endpoint = ="http://myapi....";

public void setEndpoint(String endpoint){
   ...
}

最佳答案

当然有很多解决方案,其中一种方法是使用具有默认值的系统属性:

private static final String DEFAULT_ENDPOINT = "http://myapi....";
private static final String ENDPOINT = 
        System.getProperty("my.endpoint", DEFAULT_ENDPOINT);

这样您就可以通过可配置的方式来解决您的问题。如果您在初始化静态常量时需要更大的灵活性,您还可以使用静态初始化器:

private static final String ENDPOINT;
static {
    // do initialization here but do not throw any exceptions (bad practice)
    // you can e.g. read from files etc...

    // Then assign your constant...
    ENDPOINT = 
}

系统属性作为 -D 参数在命令行上传递,例如:

java -Dmy.endpoint=http://...

但在我看来,更好的方法实际注入(inject)值到使用它的类:

public class ClassThatIsUsingTheConfig {
    private final String endpoint;
    public ClassThatIsUsingTheConfig(final String endpoint) {
        this.endpoint = endpoint;
    }

    public void someMethod() {
        // use endpoint
    }
}

然后,选择在调用者类中使用哪个端点。从测试用例来看,这将非常容易模拟。

public class MyTest {
    @Test
    public void testMethod() {
        ClassThatIsUsingTheConfig var = new ClassThatIsUsingTheConfig(TEST_ENDPOINT);
        var.someMethod();
    }
}

public class MyProdClass {
    public void prodMethod() {
        ClassThatIsUsingTheConfig var = new ClassThatIsUsingTheConfig(PROD_ENDPOINT);
        var.someMethod();
    }
}

您可以阅读有关 dependency injection here 的更多信息.


顺便说一句,如果您正在使用某种框架来管理依赖项,例如 Spring FrameworkCDI能够以各种方式注入(inject)属性和常量是很常见的(例如,基于当前正在运行的环境)。举个例子,当使用 Spring 框架时,您可以在属性文件中声明所有常量并使用注释注入(inject)属性:

@Autowired
public ClassWhoIsUsingTheConfig(@Value("my.endoint") final String endpoint) {
    this.endpoint = endpoint;
}

prod 的属性文件可能类似于:

my.endpoint=http://prodserver...


测试的属性文件如下所示:

my.endpoint=http://testserver...

使用依赖注入(inject)引擎的方法允许以非常灵活的方式处理外部常量、路径、资源等,并在测试代码时简化您的生活。

关于java - 使静态变量可注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27973349/

相关文章:

java - 使用备忘录模式(和命令)存储复杂对象的状态

java - 连接字符串和变量

java - 应用程序引擎上的可靠分布式缓存 (Java)

java - 无法在 java 匹配中加载属性-

angular - 我应该在注入(inject)的 Angular 服务上使用 readonly 而不是将它们公开吗?

c# - LoggerFactory 生成 InvalidOperationException

java - Java中逗号运算符的等价物?

java - 无法使用 son simple 解析 JSON 数组

typescript - Nestjs 依赖注入(inject) - 将服务注入(inject)服务

c# - DI Singleton 实例与 Transient 实例