简体   繁体   English

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

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

I'm wondering how should I initialize fields in Spring Beans?我想知道我应该如何初始化 Spring Beans 中的字段? Here is several possible solutions:以下是几种可能的解决方案:

1. Initialize fields directly on declaration 1. 直接在声明时初始化字段

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 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. Initialize fields using @Autowired annotation 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. Initialize fields using @PostConstruct annotation 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;
    }
}

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.假设该值是一个常量,第一个选项是最容易理解的,并且在没有 Spring 的情况下也能工作,从而简化了单元测试。

The second and fourth option are more complex and introduce an unnecessary dependency on the Spring container without any benefit.第二个和第四个选项更复杂,并且引入了对 Spring 容器的不必要依赖,没有任何好处。 The third option is outright bizarre, since you're using @Autowired and not performing dependency injection.第三个选项非常奇怪,因为您使用的是@Autowired而不是执行依赖注入。

I believe spring offers all those options because you might run into different requirements...我相信 spring 提供了所有这些选项,因为您可能会遇到不同的要求......

  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.如果你想要MAX_INT并且地球上没有任何人需要以不同的方式初始化它,那么无论 Spring 是什么,声明int field = Integer.MAX_INT就足够了。

  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.如果您确实想允许其他初始配置,那么您可以使用@Autowired或通过构造函数 arg 或 setter/getter 对其进行初始化......这是一个品味问题。

  3. @PostConstruct is more suitable for complex situations, eg if your field needs to be calculated based on other injected fields. @PostConstruct更适合复杂的情况,例如,如果您的字段需要根据其他注入的字段进行计算。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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