简体   繁体   中英

What is a right way to initialize fields in Spring Beans?

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...

  1. 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.

  2. 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.

  3. @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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM