Spring - Java Based Configuration
Spring introduced annotation-based Java configuration as a type-safe, refactor-friendly alternative to XML. A class annotated with @Configuration acts as a bean factory: methods annotated with @Bean register beans in the ApplicationContext.
Contents
@Configuration and @Bean basics
A @Configuration@Bean
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
ds.setUsername("user");
ds.setPassword("pass");
ds.setMaximumPoolSize(10);
return ds;
}
@Bean
public JdbcTemplate jdbcTemplate() {
// Calling dataSource() here returns the same singleton instance
return new JdbcTemplate(dataSource());
}
}
Declaring bean dependencies via method parameters
You can declare the dependency as a method parameter instead of calling a sibling method directly. Spring injects the correct bean automatically.
@Configuration
public class ServiceConfig {
@Bean
public UserRepository userRepository(DataSource dataSource) {
return new JdbcUserRepository(dataSource);
}
@Bean
public UserService userService(UserRepository userRepository) {
return new UserServiceImpl(userRepository);
}
}
Splitting config with @Import
Large applications can split their configuration into multiple classes and compose them with @Import
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({DataSourceConfig.class, SecurityConfig.class, CacheConfig.class})
public class RootConfig {
// Aggregates the other configuration classes into one root context
}
Conditional beans with @Conditional
Spring Boot extends the base @Conditional@ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class NotificationConfig {
@Bean
@ConditionalOnProperty(name = "notification.channel", havingValue = "email")
public NotificationService emailNotificationService() {
return new EmailNotificationService();
}
@Bean
@ConditionalOnMissingBean(NotificationService.class)
public NotificationService noOpNotificationService() {
return message -> System.out.println("NoOp: " + message);
}
}