Configuration — Cheat Sheet
Spring Boot · 5 topics. Download the PDF or the Instagram carousel and share it.
@Value Injection
Injects individual property values, Spring EL expressions, or system variables directly into fields or constructor parameters.
- ✓@Value("${key}") reads from environment/properties; #{expr} evaluates SpEL.
- ✓Default values are specified with a colon: @Value("${key:default}").
- ✓Comma-separated strings are auto-split into List<String> or arrays.
- ✓Field injection works but constructor injection is preferred for testability.
- ✓@ConfigurationProperties is better for groups of related properties (type-safe, validated).
- ✓Profile-specific files (application-{profile}.properties) override base properties automatically.
@Component
public class AppConfig {
@Value("${app.name}")
private String appName;
@Value("${app.timeout:5000}") // default 5000 if not set
private int timeoutMs;
@Value("${app.admins:admin1,admin2}")
private List<String> admins; // comma-separated → List
@Value("#{systemProperties['user.home']}")
private String userHome; // SpEL — system property
@Value("#{T(java.lang.Math).PI}")
private double pi; // SpEL — static method/field
}Bean Lifecycle & Scope
Spring manages beans through a well-defined lifecycle; scopes (singleton, prototype, request, session) determine how many instances are created and when they are destroyed.
- ✓@PostConstruct runs after all dependencies are injected — safe to use them; @PreDestroy runs on context shutdown — ideal for resource cleanup.
- ✓Singleton scope means one shared instance per context — state in singleton beans must be thread-safe.
- ✓Prototype beans are NOT destroyed by Spring — the caller is responsible for cleanup if needed.
- ✓Never inject a prototype bean into a singleton with a plain @Autowired — the prototype is only created once. Use ObjectFactory<T> or ApplicationContext.getBean() for fresh instances.
- ✓BeanPostProcessor intercepts every bean and is how Spring implements @PostConstruct, @Autowired, and AOP proxies.
- ✓Use @Scope proxyMode=TARGET_CLASS to safely inject request/session-scoped beans into singleton beans.
@Component
public class CacheService implements InitializingBean, DisposableBean {
private Map<String, String> cache;
// Phase 4+5 — runs after all dependencies are injected
@PostConstruct
public void init() {
cache = new ConcurrentHashMap<>();
System.out.println("CacheService initialised");
}
// Alternative to @PostConstruct — implements InitializingBean
@Override
public void afterPropertiesSet() {
// Same timing as @PostConstruct — pick one style
}
// Phase 8 — runs on context shutdown (Ctrl+C or System.exit)
@PreDestroy
public void cleanup() {
cache.clear();
System.out.println("CacheService destroyed");
}
@Override
public void destroy() {
// Alternative to @PreDestroy — implements DisposableBean
}
}@Configuration & @Bean
@Configuration marks a class as a source of bean definitions; @Bean methods create and configure objects that are managed by the Spring container.
- ✓@Configuration classes are CGLIB-proxied — inter-@Bean method calls return the same singleton.
- ✓@Bean methods are factory methods; Spring calls them once (singleton scope) by default.
- ✓Bean name defaults to method name; override with @Bean(name="...").
- ✓@ConditionalOnProperty, @ConditionalOnMissingBean etc. enable conditional bean creation.
- ✓@Component in "lite mode" does NOT proxy — avoid calling @Bean methods from each other.
- ✓Prefer injecting beans via @Bean method parameters over calling other @Bean methods.
@Configuration
public class DataSourceConfig {
// @Bean method — Spring calls this once and caches the result (singleton)
@Bean
public DataSource dataSource(DataSourceProperties props) {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(props.getUrl());
ds.setUsername(props.getUsername());
ds.setPassword(props.getPassword());
ds.setMaximumPoolSize(10);
return ds;
}
// Bean depending on another bean — Spring injects dataSource() singleton
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
// Custom bean name
@Bean(name = "primaryCache")
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("products", "orders");
}
// Prototype scope — new instance per injection point
@Bean
@Scope("prototype")
public OrderProcessor orderProcessor() {
return new OrderProcessor();
}
}@ComponentScan & Stereotypes
@ComponentScan instructs Spring to detect @Component, @Service, @Repository, and @Controller classes and register them as beans automatically.
- ✓@SpringBootApplication includes @ComponentScan rooted at the main class's package.
- ✓@Service, @Repository, @Controller are semantic aliases for @Component.
- ✓@Repository adds PersistenceExceptionTranslationPostProcessor — translates DB exceptions.
- ✓basePackages restricts scanning; includeFilters/excludeFilters fine-tune discovery.
- ✓Default bean name = simple class name with lowercase first letter.
- ✓Use @Qualifier to disambiguate when multiple beans of the same type exist.
// @Component — generic bean; no additional semantics
@Component
public class PasswordEncoder { ... }
// @Service — marks business logic / service layer
// No technical difference from @Component, but signals intent
@Service
public class OrderService {
public Order placeOrder(PlaceOrderRequest req) { ... }
}
// @Repository — data access layer
// Spring wraps methods to translate JDBC/JPA exceptions to DataAccessException
@Repository
public class JdbcOrderRepository {
public Optional<Order> findById(Long id) { ... }
// SQLException thrown here → auto-translated to DataAccessException
}
// @Controller — web layer (Spring MVC)
@Controller
public class OrderViewController { ... }
// @RestController — web layer for REST APIs (@Controller + @ResponseBody)
@RestController
public class OrderApiController { ... }Application Events & Listeners
Spring fires lifecycle events (ApplicationStartedEvent, ApplicationReadyEvent, etc.) that you can handle with @EventListener to run custom startup logic.
- ✓Spring fires lifecycle events in order: Starting → EnvironmentPrepared → ContextInitialized → Prepared → ContextRefreshed → Started → Ready
- ✓Use ApplicationReadyEvent for post-startup init (cache warm-up) — it fires after embedded server is ready
- ✓Custom events can be plain POJOs since Spring 4.2; use records for immutable, self-documenting events
- ✓@EventListener is synchronous (same thread); @Async @EventListener runs in a thread pool (requires @EnableAsync)
- ✓@TransactionalEventListener(phase=AFTER_COMMIT) fires only after the transaction commits — prevents side effects on rollback
- ✓Multiple @EventListener methods can handle the same event type independently — decoupled consumers
@Component
public class StartupInitializer {
private final DataCache cache;
// Runs after context is fully ready (including embedded Tomcat)
@EventListener(ApplicationReadyEvent.class)
public void onApplicationReady(ApplicationReadyEvent event) {
log.info("Application started in {}ms — warming up cache",
event.getTimeTaken().toMillis());
cache.warmUp();
}
// Runs on context refresh (also on each refresh in dev with DevTools)
@EventListener(ContextRefreshedEvent.class)
public void onContextRefreshed() {
log.debug("Context refreshed");
}
// Handle failed startup
@EventListener(ApplicationFailedEvent.class)
public void onApplicationFailed(ApplicationFailedEvent event) {
log.error("Startup failed", event.getException());
alertingService.sendAlert("Startup failure: " + event.getException().getMessage());
}
}