不要滥用通过反射获得/设置的私有字段
我们可以避免使用反射,因为在几个答案中可以做到这一点。
它在这里带来很小的价值,但同时也带来了许多缺点:
- 我们仅在运行时检测反射问题(例如:字段不再存在)
- 我们需要封装,而不是一个不透明的类,它隐藏了应该是可见的依赖关系,并使该类更不透明且更不可测试。
- 它鼓励不良的设计。今天您声明一个
@Value String field
。明天您可以在该类中声明5
或声明10
它们,甚至可能无法直接意识到您减少了该类的设计。通过一种更加可见的方法来设置这些字段(例如构造函数),您将在添加所有这些字段之前三思而后行,并且可能将它们封装到另一个类中并使用@ConfigurationProperties
。
使您的班级既可以进行整体测试也可以进行集成测试
为了能够为Spring组件类编写普通的单元测试(即没有运行的Spring容器)和集成测试,必须使该类在有或没有Spring的情况下都可用。
在不需要的单元测试中运行容器是一种不好的做法,它会减慢本地构建的速度:您不希望这样做。
我添加了此答案,因为此处似乎没有答案显示出这种区别,因此它们系统地依赖运行中的容器。
所以我认为您应该将此属性定义为类的内部:
@Component
public class Foo{
@Value("${property.value}") private String property;
//...
}
到将由Spring注入的构造函数参数中:
@Component
public class Foo{
private String property;
public Foo(@Value("${property.value}") String property){
this.property = property;
}
//...
}
单元测试示例
您可以在Foo
没有Spring的情况下实例化并注入任何值,property
这要归功于构造函数:
public class FooTest{
Foo foo = new Foo("dummyValue");
@Test
public void doThat(){
...
}
}
集成测试示例
由于具有以下properties
属性,您可以使用Spring Boot以这种简单的方式在上下文中注入属性@SpringBootTest
:
@SpringBootTest(properties="property.value=dummyValue")
public class FooTest{
@Autowired
Foo foo;
@Test
public void doThat(){
...
}
}
您可以用作替代方法, @TestPropertySource
但是会添加一个附加注释:
@SpringBootTest
@TestPropertySource("property.value=dummyValue")
public class FooTest{ ...}
使用Spring(没有Spring Boot),应该会有些复杂,但是由于很长一段时间以来我一直没有使用Spring Boot,所以我不喜欢说愚蠢的话。
附带说明:如果@Value
要设置许多字段,则将它们提取到带有注解的类@ConfigurationProperties
中更为相关,因为我们不希望构造函数具有太多参数。