在 Spring Beans 中初始化字段的正确方法是什么?
What is a right way to initialize fields in Spring Beans?
我想知道我应该如何初始化 Spring Beans 中的字段?以下是几种可能的解决方案:
1.直接在声明中初始化字段
import org.springframework.stereotype.Component;
@Component
public class DeclarationInit {
private final int field = Integer.MAX_VALUE;
public int getField() {
return field;
}
}
2。使用 @Value
注释
初始化字段
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class ValueInit {
@Value("#{T(Integer).MAX_VALUE}")
private int field;
public int getField() {
return field;
}
}
3。使用 @Autowired
注释
初始化字段
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AutowiredInit {
private int field;
@Autowired
private void initField() {
field = Integer.MAX_VALUE;
}
public int getField() {
return field;
}
}
4.使用 @PostConstruct
注释
初始化字段
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
@Component
public class PostConstructInit {
private int field;
@PostConstruct
private void initField() {
field = Integer.MAX_VALUE;
}
public int getField() {
return field;
}
}
所有测试都成功并且没有显示任何差异:
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SomeTestContextConfiguration.class)
public class FieldInitTest {
@Autowired
private DeclarationInit declarationInit;
@Autowired
private ValueInit valueInit;
@Autowired
private AutowiredInit autowiredInit;
@Autowired
private PostConstructInit postConstructInit;
@Test
public void shouldInitializeFieldOnDeclaration() {
assertThat(declarationInit.getField(), equalTo(Integer.MAX_VALUE));
}
@Test
public void shouldInitializeFieldWithValueAnnotation() {
assertThat(valueInit.getField(), equalTo(Integer.MAX_VALUE));
}
@Test
public void shouldInitializeFieldWithAutowiredSetter() {
assertThat(autowiredInit.getField(), equalTo(Integer.MAX_VALUE));
}
@Test
public void shouldInitializeFieldWithPostConstruct() {
assertThat(postConstructInit.getField(), equalTo(Integer.MAX_VALUE));
}
}
这些声明是否彼此相等,或者我应该只使用其中之一还是两者都不使用?
假设该值为常量,第一个选项最容易理解并且在没有 Spring 的情况下也能工作,简化了单元测试。
第二个和第四个选项更复杂,并且引入了对 Spring 容器的不必要依赖,没有任何好处。第三个选项非常奇怪,因为您使用的是 @Autowired
而不是执行依赖注入。
我相信 spring 提供所有这些选项,因为您可能 运行 满足不同的要求...
如果你想要MAX_INT
并且地球上没有任何人需要以不同的方式初始化它,那么无论Spring如何声明int field = Integer.MAX_INT
就足够了。
如果你确实想要允许其他初始配置,那么你可以使用@Autowired
或通过构造函数arg或setter/getter来初始化它......这是一个问题味道。
@PostConstruct
更适合复杂的情况,例如如果你的字段需要根据其他注入的字段计算。
我想知道我应该如何初始化 Spring Beans 中的字段?以下是几种可能的解决方案:
1.直接在声明中初始化字段
import org.springframework.stereotype.Component;
@Component
public class DeclarationInit {
private final int field = Integer.MAX_VALUE;
public int getField() {
return field;
}
}
2。使用 @Value
注释
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class ValueInit {
@Value("#{T(Integer).MAX_VALUE}")
private int field;
public int getField() {
return field;
}
}
3。使用 @Autowired
注释
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AutowiredInit {
private int field;
@Autowired
private void initField() {
field = Integer.MAX_VALUE;
}
public int getField() {
return field;
}
}
4.使用 @PostConstruct
注释
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
@Component
public class PostConstructInit {
private int field;
@PostConstruct
private void initField() {
field = Integer.MAX_VALUE;
}
public int getField() {
return field;
}
}
所有测试都成功并且没有显示任何差异:
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SomeTestContextConfiguration.class)
public class FieldInitTest {
@Autowired
private DeclarationInit declarationInit;
@Autowired
private ValueInit valueInit;
@Autowired
private AutowiredInit autowiredInit;
@Autowired
private PostConstructInit postConstructInit;
@Test
public void shouldInitializeFieldOnDeclaration() {
assertThat(declarationInit.getField(), equalTo(Integer.MAX_VALUE));
}
@Test
public void shouldInitializeFieldWithValueAnnotation() {
assertThat(valueInit.getField(), equalTo(Integer.MAX_VALUE));
}
@Test
public void shouldInitializeFieldWithAutowiredSetter() {
assertThat(autowiredInit.getField(), equalTo(Integer.MAX_VALUE));
}
@Test
public void shouldInitializeFieldWithPostConstruct() {
assertThat(postConstructInit.getField(), equalTo(Integer.MAX_VALUE));
}
}
这些声明是否彼此相等,或者我应该只使用其中之一还是两者都不使用?
假设该值为常量,第一个选项最容易理解并且在没有 Spring 的情况下也能工作,简化了单元测试。
第二个和第四个选项更复杂,并且引入了对 Spring 容器的不必要依赖,没有任何好处。第三个选项非常奇怪,因为您使用的是 @Autowired
而不是执行依赖注入。
我相信 spring 提供所有这些选项,因为您可能 运行 满足不同的要求...
如果你想要
MAX_INT
并且地球上没有任何人需要以不同的方式初始化它,那么无论Spring如何声明int field = Integer.MAX_INT
就足够了。如果你确实想要允许其他初始配置,那么你可以使用
@Autowired
或通过构造函数arg或setter/getter来初始化它......这是一个问题味道。@PostConstruct
更适合复杂的情况,例如如果你的字段需要根据其他注入的字段计算。