在Spring Beans中初始化字段的正确方法是什么?

ytt*_*rrr 7 java spring dependency-injection autowired in-class-initialization

我想知道如何初始化Spring Beans中的字段?这有几种可能的解决方案:

1.直接在声明上初始化字段

import org.springframework.stereotype.Component;

@Component
public class DeclarationInit {

    private final int field = Integer.MAX_VALUE;

    public int getField() {
        return field;
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

所有测试都成功,并没有显示任何差异:

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

这个声明是相互相等的还是我只使用其中一个或两者都不相同?

Eme*_*gia 7

假设值是常量,第一个选项是最简单的理解,并且在没有Spring的情况下工作,简化了单元测试.

第二个和第四个选项更复杂,并且在没有任何好处的情况下对Spring容器引入了不必要的依赖.第三种选择是彻头彻尾的奇怪,因为你正在使用@Autowired而不是执行依赖注入.