Advanced Spring Boot Interview Questions
How do you create a custom auto-configuration (starter)?
- Create a module with an
@AutoConfigurationclass that defines beans guarded by@ConditionalOnClass/@ConditionalOnMissingBean. - Bind settings with
@ConfigurationProperties. - List the class in
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Boot 3;spring.factoriesis no longer used for this). - Publish it as
shopease-audit-spring-boot-starter; any service that adds the dependency gets the beans.
What is AOP and where is it used in Spring?
Aspect-Oriented Programming moves cross-cutting concerns (logging, timing, security, transactions, caching) out of business code. Spring AOP wraps beans in proxies (JDK dynamic proxy for interfaces, CGLIB subclass otherwise). @Transactional, @Cacheable, @Async and @PreAuthorize are all implemented this way.
| Term | Meaning |
|---|---|
| Aspect | class holding the cross-cutting logic (@Aspect) |
| Join point | a method execution |
| Pointcut | expression choosing join points: execution(* com.shopease.service.*.*(..)) |
| Advice | @Before, @After, @AfterReturning, @AfterThrowing, @Around |
Why does @Transactional not work when called from the same class?
Spring applies @Transactional through a proxy. A call like this.saveOrder() inside the bean goes to the real object, bypassing the proxy, so no transaction starts. The same applies to @Async and @Cacheable. Fixes: move the method to another bean, or put @Transactional on the public method that is called from outside. Also, the method must be public (proxy-based) and checked exceptions do not roll back unless you set rollbackFor. The Coding Round shows a proxy demo.
What is Spring Boot Actuator?
spring-boot-starter-actuator adds production endpoints: /actuator/health (with liveness/readiness for Kubernetes), /info, /metrics, /prometheus, /loggers (change log level at runtime), /env, /threaddump. Only health is exposed over HTTP by default; expose others with management.endpoints.web.exposure.include and secure them.
Example
curl localhost:8080/actuator/healthExample output
{"status":"UP","components":{"db":{"status":"UP","details":{"database":"MySQL"}},"diskSpace":{"status":"UP"},"ping":{"status":"UP"}}}How do you write a custom health indicator?
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
private final PaymentClient client;
public PaymentGatewayHealthIndicator(PaymentClient client) { this.client = client; }
@Override
public Health health() {
return client.ping()
? Health.up().withDetail("gateway", "razorpay").build()
: Health.down().withDetail("gateway", "unreachable").build();
}
}How do @Async and @Scheduled work?
Enable with @EnableAsync / @EnableScheduling. @Async runs the method on a task executor and returns void or CompletableFuture (send order confirmation email without blocking the response). @Scheduled(cron = "0 0 2 * * *") runs jobs like nightly reports. Define your own ThreadPoolTaskExecutor with bounded queue size; with several app instances, use ShedLock so a scheduled job runs only once.
How does caching work in Spring Boot?
@EnableCaching // on a @Configuration class
@Service
public class ProductService {
@Cacheable(value = "products", key = "#id")
public ProductResponse findById(Long id) { ... } // DB hit only on cache miss
@CacheEvict(value = "products", key = "#id")
public void update(Long id, UpdateProductRequest req) { ... }
}The default provider is a ConcurrentHashMap; use Caffeine for a bounded local cache with TTL, or Redis to share the cache across instances.
How do you improve the performance of a Spring Boot API?
- Fix N+1 queries (JOIN FETCH /
@EntityGraph), paginate, select DTO projections. - Tune HikariCP (
maximum-pool-size) and add DB indexes. - Cache hot read data (Caffeine/Redis).
- Enable virtual threads (Boot 3.2+, Java 21):
spring.threads.virtual.enabled=true. - Move slow work (emails, invoices) to
@Asyncor a message queue. - Enable response compression; measure with Actuator/Micrometer before and after.
What are virtual threads and how do they help Spring Boot?
Java 21 virtual threads are lightweight threads managed by the JVM; a blocked virtual thread (waiting on DB/HTTP) releases its carrier OS thread. With spring.threads.virtual.enabled=true, Tomcat handles each request on a virtual thread, so a blocking app can serve far more concurrent I/O-bound requests without moving to WebFlux. The DB pool size is still the limit for DB-bound work.
Spring MVC vs Spring WebFlux?
| Spring MVC | Spring WebFlux |
|---|---|
| servlet stack, thread-per-request, blocking | reactive, non-blocking, event loop (Netty) |
| JPA/JDBC, simple code | needs reactive drivers (R2DBC, reactive Mongo) |
| most CRUD/business apps | streaming, very high concurrency, gateways |
With virtual threads, MVC covers most high-concurrency needs; choose WebFlux only when the whole stack is reactive.