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?
From the console output it's clear that Spring Context is first using no-args constructor to initialize the bean object and then calling the post-init method. The order of bean initialization is same as it's defined in the spring bean configuration file.
In spring you can initialize a bean by having the applicationContext.
Spring @Configuration annotation is part of the spring core framework. Spring Configuration annotation indicates that the class has @Bean definition methods. So Spring container can process the class and generate Spring Beans to be used in the application.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With