Skip to content

Spring Boot & Spring MVC

Mid / Senior

Auto-configuration, externalized config, the DispatcherServlet request flow, filters vs interceptors, validation, the security filter chain, @Async, test slices, and Actuator.

Created 5 October 2026

10 concepts · detail hidden

  1. 01Spring vs Spring Boot

    Spring Framework is the container, AOP, transactions, MVC, data access. Spring Boot is an opinionated layer on top that removes setup work:

    • Auto-configuration — beans configured automatically based on the classpath and properties.
    • Starters — curated dependency bundles (spring-boot-starter-web, -data-jpa) with compatible versions managed by the Boot BOM.
    • Embedded server — Tomcat/Jetty/Undertow inside an executable jar (java -jar app.jar) instead of deploying a WAR to a server.
    • Externalized configuration, Actuator (health, metrics, info endpoints), and production defaults.

    Boot doesn’t add new runtime magic — it just registers ordinary Spring beans for you.

    #c-spring-vs-spring-boot
  2. 02@SpringBootApplication and how auto-configuration works

    @SpringBootApplication = @SpringBootConfiguration (a @Configuration) + @ComponentScan (scan the main class’s package and sub-packages — classes outside it aren’t found) + @EnableAutoConfiguration.

    Auto-configuration classes are listed in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports inside the Boot jars (Boot 2.7+; previously spring.factories). Each is a configuration class guarded by conditions:

    @AutoConfiguration
    @ConditionalOnClass(DataSource.class)
    @EnableConfigurationProperties(DataSourceProperties.class)
    public class DataSourceAutoConfiguration {
        @Bean
        @ConditionalOnMissingBean            // back off if the user defined their own
        DataSource dataSource(DataSourceProperties props) { ... }
    }
    

    The key idea is @ConditionalOnMissingBean — user configuration always wins: define your own ObjectMapper or DataSource bean and Boot’s default backs off. To see what was applied and why, start with --debug (the conditions evaluation report) or use the Actuator /actuator/conditions endpoint. Exclude one with @SpringBootApplication(exclude = DataSourceAutoConfiguration.class).

    #c-springbootapplication-and-how-auto-configuration-works
  3. 03Externalized configuration and precedence

    Property sources, from highest to lowest precedence (simplified):

    1. Command-line arguments (--server.port=9090)
    2. SPRING_APPLICATION_JSON, JVM system properties (-D…)
    3. OS environment variables (SERVER_PORT=9090 — relaxed binding)
    4. Profile-specific files: application-{profile}.yml (outside the jar beats inside)
    5. application.yml / application.properties (outside the jar beats inside)
    6. @PropertySource and defaults

    Profiles: spring.profiles.active=prod activates application-prod.yml and @Profile("prod") beans. Secrets belong in environment variables or a secrets manager, not in committed YAML.

    #c-externalized-configuration-and-precedence
  4. 04The DispatcherServlet request flow
    1. Request passes through the servlet filter chain (including Spring Security).
    2. DispatcherServlet (the front controller) asks its HandlerMappings which handler matches — RequestMappingHandlerMapping maps URL + method to a @GetMapping method.
    3. HandlerInterceptor.preHandle for each interceptor.
    4. HandlerAdapter invokes the method: argument resolvers bind @PathVariable, @RequestParam, @RequestBody (via an HttpMessageConverter — Jackson for JSON) and run @Valid validation.
    5. Return value handled: for @RestController/@ResponseBody, serialized by a message converter (content negotiation on Accept); otherwise resolved by a ViewResolver.
    6. postHandle, then afterCompletion interceptors.
    7. Exceptions anywhere in 3–5 go to HandlerExceptionResolvers — including @ExceptionHandler/@ControllerAdvice. Global error handling — how a handler is chosen, ProblemDetail error bodies, and what Boot does when nothing handles an exception — is covered in the Exception handling subtopic.
    #c-the-dispatcherservlet-request-flow
  5. 05Filters vs HandlerInterceptors vs AOP
    Servlet Filter HandlerInterceptor AOP aspect
    Level Servlet container, before DispatcherServlet Spring MVC, around the handler Any Spring bean method
    Sees Raw request/response; can wrap them Request + the resolved handler method Method arguments/return value
    Typical use Security, CORS, logging, compression, request ids Auth checks per handler, locale, timing Transactions, auditing, metrics on services
    Applies to Every request, including static resources and errors Only requests mapped to handlers Only proxied bean calls

    Rule of thumb: cross-cutting HTTP concerns → filter; concerns that need to know which controller method → interceptor; business-layer concerns → AOP.

    #c-filters-vs-handlerinterceptors-vs-aop
  6. 06Validation — @Valid and @Validated
    • @Valid @RequestBody CreateOrder body triggers Jakarta Bean Validation (@NotNull, @Size, @Email on the DTO’s fields); failures → MethodArgumentNotValidException → 400.
    • @Validated on a class enables method-level validation through a proxy (constraints on service method parameters, @ConfigurationProperties validation) and supports validation groups.
    • @Valid on a field cascades validation into nested objects.
    #c-validation-valid-and-validated
  7. 07Spring Security's filter chain in one minute

    Spring Security is a chain of servlet filters: DelegatingFilterProxy (registered with the servlet container) delegates to FilterChainProxy, which picks the first matching SecurityFilterChain bean and runs its filters — CORS, CSRF, authentication (UsernamePasswordAuthenticationFilter, BearerTokenAuthenticationFilter for JWT), then ExceptionTranslationFilter and AuthorizationFilter. A successful authentication is stored in the SecurityContextHolder (thread-local by default), which is what @PreAuthorize — another proxy-based feature, enabled with @EnableMethodSecurity — reads.

    Since Spring Security 6 you configure it by declaring a SecurityFilterChain @Bean with the lambda DSL; WebSecurityConfigurerAdapter is gone.

    #c-spring-securitys-filter-chain-in-one-minute
  8. 08@Async and scheduling

    @EnableAsync + @Async runs a method on a TaskExecutor via a proxy — so the same self-invocation and visibility rules apply. Return void or CompletableFuture<T>; exceptions from void methods go to an AsyncUncaughtExceptionHandler, otherwise they’re easy to lose. The async thread has no transaction, no SecurityContext and no request scope from the caller unless you propagate them (e.g. a TaskDecorator). Configure a bounded executor rather than relying on the default. @Scheduled(fixedRate = …) / cron with @EnableScheduling runs on a single scheduler thread by default — one slow job delays the others — and every instance of a horizontally scaled app runs it (use ShedLock or a distributed scheduler).

    #c-async-and-scheduling
  9. 09Testing — @SpringBootTest vs test slices
    • @SpringBootTest — full application context; most realistic, slowest. Combine with webEnvironment = RANDOM_PORT for real HTTP tests.
    • @WebMvcTest(OrderController.class) — only the MVC layer (controllers, advice, filters, converters) with MockMvc; services are mocked.
    • @DataJpaTest — only JPA: entities, repositories, an embedded or Testcontainers database; each test transactional and rolled back.
    • @JsonTest, @RestClientTest — other slices.

    Mock beans with @MockitoBean (Spring Framework 6.2+; Boot’s @MockBean is deprecated since Boot 3.4). Each distinct set of mocked beans/config creates a new cached context — mocks sprinkled differently across test classes slow suites down. Testcontainers with @ServiceConnection runs a real PostgreSQL in Docker — preferred over H2, whose SQL dialect and locking behaviour differ from production.

    #c-testing-springboottest-vs-test-slices
  10. 10Actuator essentials

    spring-boot-starter-actuator exposes operational endpoints: /actuator/health (with liveness/readiness groups for Kubernetes probes, aggregating DB, disk, broker checks), /actuator/metrics and /actuator/prometheus (Micrometer), /actuator/info, /actuator/env, /actuator/loggers (change log levels at runtime), /actuator/threaddump. Only health is exposed over HTTP by default; expose others deliberately (management.endpoints.web.exposure.include) and secure them — env and heapdump leak secrets.

    #c-actuator-essentials