Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 460
ytterrr Avatar asked Nov 18 '15 09:11

ytterrr


People also ask

How are Spring beans initialized?

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.

Which of the following is the most suitable way to initialize the bean?

In spring you can initialize a bean by having the applicationContext.

What is @configuration and @bean in Spring?

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.


1 Answers

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.

like image 71
Emerson Farrugia Avatar answered Oct 14 '22 10:10

Emerson Farrugia