Java configuration

@Configuration

@Configuration 
@PropertySource("classpath:example.properties") 
public class ApplicationConfiguration { 
 
    @Bean 
    public MessageBean getMessageBean() { 
        return new HelloWorldBean(); 
    } 
 
    @Bean(name = "message") 
    public String getMessage( @Value("${bean.message}") String message) { 
        return message; 
    } 
} 

Usage

public class SpringApplicationMain {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
        MessageBean messageBean = applicationContext.getBean(MessageBean.class);
        System.out.println("->" + messageBean.getMessage());
    }
}

Tests

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ApplicationConfiguration.class)
public class ApplicationConfigurationTest {

    public static final String MESSAGE = "this is a bean";
    /**
     * Complex example with the use of annotations and autowire
     */
    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    MessageBean messageBean;


    @Test
    public void testApplicationContext() {
        Assertions.assertNotNull(applicationContext);
        MessageBean messageBean = applicationContext.getBean(MessageBean.class);
        Assertions.assertEquals(MESSAGE, messageBean.getMessage());
    }
}

Configuration

Configuration metadata, contains bean definitions, can use Import to import other configurations.

@Import({Configuration.class,OtherConfiguration.class})

PropertySource

Adds additional properties, prefixes (“classpath”,”file” and “http”).

@PropertySource(“classpath:/com/example/example.properties”)

@PropertySource(“file:config/example.properties”)

Tests

To configure Spring context in Spring a combination of annotations can be used.

Configures Junit to use Spring Context, can use @ContextConfiguration to set configuration class. @ContextConfiguration(classes = ApplicationConfiguration.class)

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ApplicationConfiguration.class)
public class AutoWiringTypesTest {

    @Autowired
    @Qualifier("fruitSaladConstructor")
    FruitSaladConstructor fruitSaladConstructor;
....
}

Annotations @ExtendWith and @ContextConfiguration can be replaced with @SpringJUnitConfig or @SpringJUnitWebConfig.

@SpringJUnitConfig(SpringJUnitConfigIntegrationTest.Config.class)
public class SpringJUnitConfigIntegrationTest {

    @Configuration
    static class Config {}
}

Annotation configuration

Using @ComponentScan and stereotypes.

@Configuration
@PropertySource("classpath:example.properties")
@ComponentScan
public class ApplicationConfiguration {
...
...
...
@Service
public class SomeService {

 @Value("${service.message}")
 private String message = "";

 public String getMessage() {
    return message;
 }
}

Autowired

Usage of @Autowired

Constructor injection

@Autowired
public TransferServiceImpl(AccountRepository repository){..}

Method

@Autowired
public void setAccountRepository(AccountRepository)

Field injection (discouraged)

@Autowired
private AccountRepository accountRepository;

By default autowired beans are required but this be changed: @Autowired(required=false)

Optional is also supported:

@Autowired
public void setAccountService(Optional<AccountService> optAccountService){..}

Disambiguation

@Qualifier is used for disambiguation, can be used both for components and beans (names).

@Autowired
public TransferServiceImpl(@Qualifier("jdbc") AccountRepository ar){ ..}

@Component("jdbc")
public class MyJDBCAccountRepositoryImp{
..}

Autowiring resolution rules:

  • look for unique bean of request type
  • use @Qualifier if present
  • try to find bean matching by name

Configuration choices

If a class has only a default constructor -> no need to annotate with @Autowired

if class had only one non-default constructor -> no need to annotate with @Autowired

if class has more than one constructor -> Spring will call zero-argument by default or @Autowired must be used

Constructor vs setter

Constructor
– mandatory dependencies
– dependencies can be immutable
– concise
Setter
– can allow for circular dependencies
– dependencies are mutable
– can be verbose
– inherit automatically

Lazy beans

Lazy beans can be useful when the component is not available at startup, are created when:

  • dependency is injected
  • calling ApplicationContext.getBean()
@Component("myService")
@Lazy(true)
public class MyServiceImpl implements MyService{
...
}
@Configuration
public class ApplicationConfig{
 @Autowired
 @Lazy(true)
 public MyService getMyService(){
 ..
 }
}