I'm wondering how should I initialize fields in Spring Beans? Here is several possible solutions:
1. Initialize fields directly on declaration
import org.springframework.stereotype.Component;
@Component
public class DeclarationInit {
private final int field = Integer.MAX_VALUE;
public int getField() {
return field;
}
}
2. Initialize fields using @Value
annotation
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. Initialize fields using @Autowired
annotation
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. Initialize fields using @PostConstruct
annotation
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;
}
}
All tests succeeds and do not show any difference:
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));
}
}
Are this declarations equal to each other or should I use only one of them or neither of them?
Assuming the value is a constant, the first option is the simplest to understand and works without Spring, simplifying unit testing.
The second and fourth option are more complex and introduce an unnecessary dependency on the Spring container without any benefit. The third option is outright bizarre, since you're using @Autowired
and not performing dependency injection.
I believe spring offers all those options because you might run into different requirements...
If you want MAX_INT
and there's no way on earth anyone needs to initialize it differently, then it's enough to declare int field = Integer.MAX_INT
regardless of Spring.
If you do want to allow other initial configurations, then you can initialize it using @Autowired
, or through a constructor arg, or setter/getter... it's a matter of taste.
@PostConstruct
is more suitable for complex situations, eg if your field needs to be calculated based on other injected fields.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.